mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-27 15:17:59 +01:00
New food system:
- Foods fill for different amounts for different races - Certain foods can no longer be eaten by certain races - Added food categories for candy, rocks, desserts - Moved everything to datapacks
This commit is contained in:
parent
16a7b96f81
commit
ad7a7d84c0
74 changed files with 723 additions and 891 deletions
|
@ -1,7 +1,5 @@
|
||||||
package com.minelittlepony.unicopia;
|
package com.minelittlepony.unicopia;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.item.toxin.Toxics;
|
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.entity.EntityType;
|
import net.minecraft.entity.EntityType;
|
||||||
import net.minecraft.entity.damage.DamageType;
|
import net.minecraft.entity.damage.DamageType;
|
||||||
|
@ -79,8 +77,4 @@ public interface UTags {
|
||||||
static TagKey<DimensionType> dimension(String name) {
|
static TagKey<DimensionType> dimension(String name) {
|
||||||
return TagKey.of(RegistryKeys.DIMENSION_TYPE, new Identifier("c", name));
|
return TagKey.of(RegistryKeys.DIMENSION_TYPE, new Identifier("c", name));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void bootstrap() {
|
|
||||||
Toxics.bootstrap();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,8 @@ import com.minelittlepony.unicopia.command.Commands;
|
||||||
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
||||||
import com.minelittlepony.unicopia.container.SpellbookChapterLoader;
|
import com.minelittlepony.unicopia.container.SpellbookChapterLoader;
|
||||||
import com.minelittlepony.unicopia.container.UScreenHandlers;
|
import com.minelittlepony.unicopia.container.UScreenHandlers;
|
||||||
import com.minelittlepony.unicopia.diet.AfflictionType;
|
|
||||||
import com.minelittlepony.unicopia.diet.DietsLoader;
|
import com.minelittlepony.unicopia.diet.DietsLoader;
|
||||||
|
import com.minelittlepony.unicopia.diet.affliction.AfflictionType;
|
||||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||||
import com.minelittlepony.unicopia.entity.effect.UPotions;
|
import com.minelittlepony.unicopia.entity.effect.UPotions;
|
||||||
import com.minelittlepony.unicopia.entity.mob.UEntities;
|
import com.minelittlepony.unicopia.entity.mob.UEntities;
|
||||||
|
@ -66,7 +66,6 @@ public class Unicopia implements ModInitializer {
|
||||||
@Override
|
@Override
|
||||||
public void onInitialize() {
|
public void onInitialize() {
|
||||||
Channel.bootstrap();
|
Channel.bootstrap();
|
||||||
UTags.bootstrap();
|
|
||||||
UCriteria.bootstrap();
|
UCriteria.bootstrap();
|
||||||
UEntities.bootstrap();
|
UEntities.bootstrap();
|
||||||
Commands.bootstrap();
|
Commands.bootstrap();
|
||||||
|
|
|
@ -1,23 +1,22 @@
|
||||||
package com.minelittlepony.unicopia.diet;
|
package com.minelittlepony.unicopia.diet;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.item.toxin.Toxicity;
|
import com.minelittlepony.unicopia.diet.affliction.Affliction;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
|
||||||
public record Ailment(Toxicity toxicity, Affliction effects) {
|
public record Ailment(Affliction effects) {
|
||||||
|
public static final Ailment EMPTY = new Ailment(Affliction.EMPTY);
|
||||||
public static final Codec<Ailment> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
public static final Codec<Ailment> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
Toxicity.CODEC.fieldOf("toxicity").forGetter(Ailment::toxicity),
|
|
||||||
Affliction.CODEC.fieldOf("effects").forGetter(Ailment::effects)
|
Affliction.CODEC.fieldOf("effects").forGetter(Ailment::effects)
|
||||||
).apply(instance, Ailment::new));
|
).apply(instance, Ailment::new));
|
||||||
|
|
||||||
public Ailment(PacketByteBuf buffer) {
|
public Ailment(PacketByteBuf buffer) {
|
||||||
this(Toxicity.byName(buffer.readString()), Affliction.read(buffer));
|
this(Affliction.read(buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toBuffer(PacketByteBuf buffer) {
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
buffer.writeString(toxicity.name());
|
|
||||||
Affliction.write(buffer, effects);
|
Affliction.write(buffer, effects);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -8,30 +8,43 @@ import java.util.Set;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.item.ItemDuck;
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
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.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.registry.RegistryKeys;
|
import net.minecraft.registry.RegistryKeys;
|
||||||
import net.minecraft.registry.tag.TagKey;
|
import net.minecraft.registry.tag.TagKey;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
|
import net.minecraft.util.UseAction;
|
||||||
|
|
||||||
public record DietProfile(
|
public record DietProfile(
|
||||||
float defaultMultiplier,
|
float defaultMultiplier,
|
||||||
float foragingMultiplier,
|
float foragingMultiplier,
|
||||||
List<Multiplier> multipliers,
|
List<Multiplier> multipliers,
|
||||||
List<Effect> effects
|
List<Effect> effects,
|
||||||
|
Optional<Effect> 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(
|
public static final Codec<DietProfile> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
Codec.FLOAT.fieldOf("default_multiplier").forGetter(DietProfile::defaultMultiplier),
|
Codec.FLOAT.fieldOf("default_multiplier").forGetter(DietProfile::defaultMultiplier),
|
||||||
Codec.FLOAT.fieldOf("foraging_multiplier").forGetter(DietProfile::foragingMultiplier),
|
Codec.FLOAT.fieldOf("foraging_multiplier").forGetter(DietProfile::foragingMultiplier),
|
||||||
Codec.list(Multiplier.CODEC).fieldOf("multipliers").forGetter(DietProfile::multipliers),
|
Codec.list(Multiplier.CODEC).fieldOf("multipliers").forGetter(DietProfile::multipliers),
|
||||||
Codec.list(Effect.CODEC).fieldOf("effects").forGetter(DietProfile::effects)
|
Codec.list(Effect.CODEC).fieldOf("effects").forGetter(DietProfile::effects),
|
||||||
|
Effect.CODEC.optionalFieldOf("default_effect").forGetter(DietProfile::defaultEffect)
|
||||||
).apply(instance, DietProfile::new));
|
).apply(instance, DietProfile::new));
|
||||||
|
|
||||||
public DietProfile(PacketByteBuf buffer) {
|
public DietProfile(PacketByteBuf buffer) {
|
||||||
this(buffer.readFloat(), buffer.readFloat(), buffer.readList(Multiplier::new), buffer.readList(Effect::new));
|
this(buffer.readFloat(), buffer.readFloat(), buffer.readList(Multiplier::new), buffer.readList(Effect::new), buffer.readOptional(Effect::new));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toBuffer(PacketByteBuf buffer) {
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
|
@ -39,6 +52,7 @@ public record DietProfile(
|
||||||
buffer.writeFloat(foragingMultiplier);
|
buffer.writeFloat(foragingMultiplier);
|
||||||
buffer.writeCollection(multipliers, (b, t) -> t.toBuffer(b));
|
buffer.writeCollection(multipliers, (b, t) -> t.toBuffer(b));
|
||||||
buffer.writeCollection(effects, (b, t) -> t.toBuffer(b));
|
buffer.writeCollection(effects, (b, t) -> t.toBuffer(b));
|
||||||
|
buffer.writeOptional(defaultEffect, (b, t) -> t.toBuffer(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Multiplier> findMultiplier(ItemStack stack) {
|
public Optional<Multiplier> findMultiplier(ItemStack stack) {
|
||||||
|
@ -46,7 +60,68 @@ public record DietProfile(
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Effect> findEffect(ItemStack stack) {
|
public Optional<Effect> findEffect(ItemStack stack) {
|
||||||
return effects.stream().filter(m -> m.test(stack)).findFirst();
|
return effects.stream().filter(m -> m.test(stack)).findFirst().or(this::defaultEffect);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean isForaged(ItemStack stack) {
|
||||||
|
return ((ItemDuck)stack.getItem()).getOriginalFoodComponent().isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
public FoodComponent getAdjustedFoodComponent(ItemStack stack) {
|
||||||
|
var food = stack.getItem().getFoodComponent();
|
||||||
|
if (this == EMPTY) {
|
||||||
|
return food;
|
||||||
|
}
|
||||||
|
|
||||||
|
var ratios = getRatios(stack);
|
||||||
|
if (isInedible(ratios)) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return FoodAttributes.copy(food)
|
||||||
|
.hunger(Math.max(1, (int)(food.getHunger() * ratios.getFirst())))
|
||||||
|
.saturationModifier(food.getSaturationModifier() * ratios.getSecond())
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInedible(ItemStack stack) {
|
||||||
|
return isInedible(getRatios(stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isInedible(Pair<Float, Float> ratios) {
|
||||||
|
return ratios.getFirst() <= 0.01F && ratios.getSecond() <= 0.01F;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Pair<Float, Float> getRatios(ItemStack stack) {
|
||||||
|
Optional<Multiplier> multiplier = findMultiplier(stack);
|
||||||
|
|
||||||
|
float baseMultiplier = (isForaged(stack) ? foragingMultiplier() : defaultMultiplier());
|
||||||
|
float hungerMultiplier = multiplier.map(Multiplier::hunger).orElse(baseMultiplier);
|
||||||
|
float saturationMultiplier = multiplier.map(Multiplier::saturation).orElse(baseMultiplier);
|
||||||
|
return Pair.of(hungerMultiplier, saturationMultiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void appendTooltip(ItemStack stack, @Nullable PlayerEntity user, List<Text> tooltip, TooltipContext context) {
|
||||||
|
var food = stack.getItem().getFoodComponent();
|
||||||
|
var ratios = getRatios(stack);
|
||||||
|
if (food == null || isInedible(ratios)) {
|
||||||
|
if (stack.getUseAction() != UseAction.DRINK) {
|
||||||
|
tooltip.add(Text.literal(" ").append(Text.translatable("unicopia.diet.not_edible")).formatted(Formatting.DARK_GRAY));
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
float baseMultiplier = (isForaged(stack) ? foragingMultiplier() : defaultMultiplier());
|
||||||
|
|
||||||
|
if (context.isAdvanced()) {
|
||||||
|
tooltip.add(Text.literal(" ").append(Text.translatable("unicopia.diet.base_multiplier", baseMultiplier).formatted(Formatting.DARK_GRAY)));
|
||||||
|
tooltip.add(Text.literal(" ").append(Text.translatable("unicopia.diet.hunger.detailed", Math.max(1, (int)(ratios.getFirst() * food.getHunger())), food.getHunger(), (int)(ratios.getFirst() * 100))).formatted(Formatting.DARK_GRAY));
|
||||||
|
tooltip.add(Text.literal(" ").append(Text.translatable("unicopia.diet.saturation.detailed", String.format("%.2f", ratios.getSecond() * food.getSaturationModifier()), (int)(ratios.getSecond() * 100))).formatted(Formatting.DARK_GRAY));
|
||||||
|
} else {
|
||||||
|
tooltip.add(Text.literal(" ").append(Text.translatable("unicopia.diet.hunger", (int)(ratios.getFirst() * 100))).formatted(Formatting.DARK_GRAY));
|
||||||
|
tooltip.add(Text.literal(" ").append(Text.translatable("unicopia.diet.saturation", (int)(ratios.getSecond() * 100))).formatted(Formatting.DARK_GRAY));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public record Multiplier(
|
public record Multiplier(
|
||||||
|
|
27
src/main/java/com/minelittlepony/unicopia/diet/DietView.java
Normal file
27
src/main/java/com/minelittlepony/unicopia/diet/DietView.java
Normal file
|
@ -0,0 +1,27 @@
|
||||||
|
package com.minelittlepony.unicopia.diet;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import net.minecraft.client.item.TooltipContext;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.TypedActionResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
|
public interface DietView {
|
||||||
|
TypedActionResult<ItemStack> startUsing(ItemStack stack, World world, PlayerEntity user, Hand hand);
|
||||||
|
|
||||||
|
void finishUsing(ItemStack stack, World world, LivingEntity entity);
|
||||||
|
|
||||||
|
void appendTooltip(ItemStack stack, @Nullable PlayerEntity user, List<Text> tooltip, TooltipContext context);
|
||||||
|
|
||||||
|
interface Holder {
|
||||||
|
default DietView getDiets(ItemStack stack) {
|
||||||
|
return PonyDiets.getInstance();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -40,23 +40,34 @@ public class DietsLoader implements IdentifiableResourceReloadListener {
|
||||||
Map<Race, DietProfile> profiles = new HashMap<>();
|
Map<Race, DietProfile> profiles = new HashMap<>();
|
||||||
for (var entry : data.entrySet()) {
|
for (var entry : data.entrySet()) {
|
||||||
Identifier id = entry.getKey();
|
Identifier id = entry.getKey();
|
||||||
Race.REGISTRY.getOrEmpty(id).ifPresentOrElse(race -> DietProfile.CODEC.parse(JsonOps.INSTANCE, entry.getValue())
|
try {
|
||||||
.resultOrPartial(LOGGER::error)
|
Race.REGISTRY.getOrEmpty(id).ifPresentOrElse(race -> {
|
||||||
.ifPresent(profile -> profiles.put(race, profile)), () -> LOGGER.warn("Skipped diet for unknown race: " + id));
|
DietProfile.CODEC.parse(JsonOps.INSTANCE, entry.getValue())
|
||||||
|
.resultOrPartial(error -> LOGGER.error("Could not load diet profile {}: {}", id, error))
|
||||||
|
.ifPresent(profile -> profiles.put(race, profile));
|
||||||
|
}, () -> LOGGER.warn("Skipped diet for unknown race: " + id));
|
||||||
|
} catch (Throwable t) {
|
||||||
|
LOGGER.error("Could not load diet profile {}", id, t);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return profiles;
|
return profiles;
|
||||||
}, applyExecutor);
|
}, prepareExecutor);
|
||||||
|
|
||||||
var effectsLoadTask = loadData(manager, prepareExecutor, "diets/food_effects").thenApplyAsync(data -> data.values().stream()
|
var effectsLoadTask = loadData(manager, prepareExecutor, "diets/food_effects").thenApplyAsync(data -> data.entrySet().stream()
|
||||||
.map(value -> Effect.CODEC.parse(JsonOps.INSTANCE, value)
|
.map(entry -> {
|
||||||
.resultOrPartial(LOGGER::error))
|
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)
|
.filter(Optional::isPresent)
|
||||||
.map(Optional::get)
|
.map(Optional::get)
|
||||||
.toList());
|
.toList(), prepareExecutor);
|
||||||
|
|
||||||
var future = CompletableFuture.allOf(dietsLoadTask, effectsLoadTask);
|
return CompletableFuture.allOf(dietsLoadTask, effectsLoadTask).thenCompose(sync::whenPrepared).thenRunAsync(() -> {
|
||||||
sync.getClass();
|
|
||||||
return future.thenRunAsync(() -> {
|
|
||||||
PonyDiets.load(new PonyDiets(
|
PonyDiets.load(new PonyDiets(
|
||||||
dietsLoadTask.getNow(Map.of()),
|
dietsLoadTask.getNow(Map.of()),
|
||||||
effectsLoadTask.getNow(List.of())
|
effectsLoadTask.getNow(List.of())
|
||||||
|
|
|
@ -1,56 +1,76 @@
|
||||||
package com.minelittlepony.unicopia.diet;
|
package com.minelittlepony.unicopia.diet;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
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.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.registry.RegistryKeys;
|
import net.minecraft.registry.RegistryKeys;
|
||||||
import net.minecraft.registry.tag.TagKey;
|
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(
|
public record Effect(
|
||||||
TagKey<Item> tag,
|
List<TagKey<Item>> tags,
|
||||||
Optional<FoodComponent> foodComponent,
|
Optional<FoodComponent> foodComponent,
|
||||||
Ailment ailment
|
Ailment ailment
|
||||||
) implements Predicate<ItemStack> {
|
) 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(
|
public static final Codec<Effect> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
TagKey.unprefixedCodec(RegistryKeys.ITEM).fieldOf("tag").forGetter(Effect::tag),
|
TagKey.unprefixedCodec(RegistryKeys.ITEM).listOf().fieldOf("tags").forGetter(Effect::tags),
|
||||||
FoodComponent.CODEC.optionalFieldOf("food_component").forGetter(Effect::foodComponent),
|
FoodAttributes.CODEC.optionalFieldOf("food_component").forGetter(Effect::foodComponent),
|
||||||
Ailment.CODEC.fieldOf("ailment").forGetter(Effect::ailment)
|
Ailment.CODEC.fieldOf("ailment").forGetter(Effect::ailment)
|
||||||
).apply(instance, Effect::new));
|
).apply(instance, Effect::new));
|
||||||
|
|
||||||
public Effect(PacketByteBuf buffer) {
|
public Effect(PacketByteBuf buffer) {
|
||||||
this(TagKey.of(RegistryKeys.ITEM, buffer.readIdentifier()), buffer.readOptional(FoodComponent::new), new Ailment(buffer));
|
this(buffer.readList(b -> TagKey.of(RegistryKeys.ITEM, b.readIdentifier())), buffer.readOptional(FoodAttributes::read), new Ailment(buffer));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void afflict(Pony pony, ItemStack stack) {
|
||||||
|
ailment().effects().afflict(pony.asEntity(), stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
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) {
|
||||||
|
if (stack.isFood()) {
|
||||||
|
tooltip.add(Text.literal(" ").append(Text.translatable("tag.unicopia.food_types.fruits_and_vegetables")).formatted(Formatting.GRAY));
|
||||||
|
} else if (stack.getUseAction() == UseAction.DRINK) {
|
||||||
|
tooltip.add(Text.literal(" ").append(Text.translatable("tag.unicopia.food_types.drinks")).formatted(Formatting.GRAY));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (context.isAdvanced() && stack.isFood()) {
|
||||||
|
if (!ailment().effects().isEmpty()) {
|
||||||
|
tooltip.add(Text.translatable("unicopia.diet.side_effects").formatted(Formatting.DARK_PURPLE));
|
||||||
|
ailment().effects().appendTooltip(tooltip);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void toBuffer(PacketByteBuf buffer) {
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
buffer.writeIdentifier(tag.id());
|
buffer.writeCollection(tags, (b, t) -> b.writeIdentifier(t.id()));
|
||||||
buffer.writeOptional(foodComponent, (b, f) -> f.toBuffer(b));
|
buffer.writeOptional(foodComponent, FoodAttributes::write);
|
||||||
ailment.toBuffer(buffer);
|
ailment.toBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean test(ItemStack stack) {
|
public boolean test(ItemStack stack) {
|
||||||
return stack.isIn(tag);
|
return tags.stream().anyMatch(stack::isIn);
|
||||||
}
|
|
||||||
|
|
||||||
public record FoodComponent (float hunger, float saturation) {
|
|
||||||
public static final Codec<FoodComponent> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
|
||||||
Codec.FLOAT.fieldOf("hunger").forGetter(FoodComponent::hunger),
|
|
||||||
Codec.FLOAT.fieldOf("saturation").forGetter(FoodComponent::saturation)
|
|
||||||
).apply(instance, FoodComponent::new));
|
|
||||||
|
|
||||||
public FoodComponent(PacketByteBuf buffer) {
|
|
||||||
this(buffer.readFloat(), buffer.readFloat());
|
|
||||||
}
|
|
||||||
|
|
||||||
public void toBuffer(PacketByteBuf buffer) {
|
|
||||||
buffer.writeFloat(hunger);
|
|
||||||
buffer.writeFloat(saturation);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -0,0 +1,60 @@
|
||||||
|
package com.minelittlepony.unicopia.diet;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import com.mojang.datafixers.util.Pair;
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
|
||||||
|
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||||
|
import net.minecraft.item.FoodComponent;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
|
||||||
|
final class FoodAttributes {
|
||||||
|
static final Codec<FoodComponent> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
|
Codec.INT.fieldOf("hunger").forGetter(FoodComponent::getHunger),
|
||||||
|
Codec.FLOAT.fieldOf("saturation").forGetter(FoodComponent::getSaturationModifier),
|
||||||
|
Codec.BOOL.optionalFieldOf("petFood", false).forGetter(FoodComponent::isMeat),
|
||||||
|
Codec.BOOL.optionalFieldOf("fastFood", false).forGetter(FoodComponent::isAlwaysEdible),
|
||||||
|
Codec.BOOL.optionalFieldOf("eatenQuickly", false).forGetter(FoodComponent::isSnack)
|
||||||
|
).apply(instance, FoodAttributes::create));
|
||||||
|
|
||||||
|
static FoodComponent create(int hunger, float saturation, boolean petFood, boolean fastFood, boolean eatenQuickly) {
|
||||||
|
return create(hunger, saturation, petFood, fastFood, eatenQuickly, List.of()).build();
|
||||||
|
}
|
||||||
|
|
||||||
|
static FoodComponent.Builder create(int hunger, float saturation, boolean petFood, boolean fastFood, boolean eatenQuickly, List<Pair<StatusEffectInstance, Float>> effects) {
|
||||||
|
var builder = new FoodComponent.Builder()
|
||||||
|
.hunger(hunger)
|
||||||
|
.saturationModifier(saturation);
|
||||||
|
if (petFood) {
|
||||||
|
builder.meat();
|
||||||
|
}
|
||||||
|
if (fastFood) {
|
||||||
|
builder.alwaysEdible();
|
||||||
|
}
|
||||||
|
if (eatenQuickly) {
|
||||||
|
builder.snack();
|
||||||
|
}
|
||||||
|
for (var effect : effects) {
|
||||||
|
builder.statusEffect(effect.getFirst(), effect.getSecond());
|
||||||
|
}
|
||||||
|
return builder;
|
||||||
|
}
|
||||||
|
|
||||||
|
static FoodComponent.Builder copy(FoodComponent food) {
|
||||||
|
return create(food.getHunger(), food.getSaturationModifier(), food.isMeat(), food.isAlwaysEdible(), food.isSnack(), food.getStatusEffects());
|
||||||
|
}
|
||||||
|
|
||||||
|
static FoodComponent read(PacketByteBuf buffer) {
|
||||||
|
return create(buffer.readInt(), buffer.readFloat(), buffer.readBoolean(), buffer.readBoolean(), buffer.readBoolean());
|
||||||
|
}
|
||||||
|
|
||||||
|
static void write(PacketByteBuf buffer, FoodComponent food) {
|
||||||
|
buffer.writeInt(food.getHunger());
|
||||||
|
buffer.writeFloat(food.getSaturationModifier());
|
||||||
|
buffer.writeBoolean(food.isMeat());
|
||||||
|
buffer.writeBoolean(food.isAlwaysEdible());
|
||||||
|
buffer.writeBoolean(food.isSnack());
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,43 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.diet;
|
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.item.FoodComponent;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.network.PacketByteBuf;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
|
|
||||||
public record MultiplyHungerAffliction(float multiplier) implements Affliction {
|
|
||||||
public static final Codec<MultiplyHungerAffliction> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
|
||||||
Codec.FLOAT.fieldOf("multiplier").forGetter(MultiplyHungerAffliction::multiplier)
|
|
||||||
).apply(instance, MultiplyHungerAffliction::new));
|
|
||||||
|
|
||||||
public MultiplyHungerAffliction(PacketByteBuf buffer) {
|
|
||||||
this(buffer.readFloat());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void toBuffer(PacketByteBuf buffer) {
|
|
||||||
buffer.writeFloat(multiplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public AfflictionType<?> getType() {
|
|
||||||
return AfflictionType.MULTIPLY_HUNGER;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void afflict(PlayerEntity player, ItemStack stack) {
|
|
||||||
FoodComponent food = stack.getItem().getFoodComponent();
|
|
||||||
player.getHungerManager().setFoodLevel((int)(food.getHunger() * multiplier));
|
|
||||||
player.getHungerManager().setSaturationLevel(food.getSaturationModifier() * multiplier);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Text getName() {
|
|
||||||
return Text.translatable("Lose %s%% hunger", multiplier * 100);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -4,20 +4,30 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.Race;
|
import org.jetbrains.annotations.Nullable;
|
||||||
import com.minelittlepony.unicopia.diet.DietProfile.Multiplier;
|
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.Race;
|
||||||
|
import com.minelittlepony.unicopia.entity.effect.FoodPoisoningStatusEffect;
|
||||||
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
import com.minelittlepony.unicopia.item.ItemDuck;
|
||||||
|
import net.minecraft.client.item.TooltipContext;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.util.TypedActionResult;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class PonyDiets {
|
public class PonyDiets implements DietView {
|
||||||
private final Map<Race, DietProfile> diets;
|
private final Map<Race, DietProfile> diets;
|
||||||
private final List<Effect> effects;
|
private final List<Effect> effects;
|
||||||
|
|
||||||
static PonyDiets INSTANCE = new PonyDiets(Map.of(), List.of());
|
private static PonyDiets INSTANCE = new PonyDiets(Map.of(), List.of());
|
||||||
|
|
||||||
public static PonyDiets getinstance() {
|
public static PonyDiets getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -39,19 +49,61 @@ public class PonyDiets {
|
||||||
buffer.writeCollection(effects, (b, e) -> e.toBuffer(b));
|
buffer.writeCollection(effects, (b, e) -> e.toBuffer(b));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<DietProfile> getDiet(Race race) {
|
private DietProfile getDiet(Pony pony) {
|
||||||
return Optional.ofNullable(diets.get(race));
|
return Optional.ofNullable(diets.get(pony.getObservedSpecies())).orElse(DietProfile.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Effect> getEffects(ItemStack stack) {
|
private Effect getEffects(ItemStack stack) {
|
||||||
return effects.stream().filter(effect -> effect.test(stack)).findFirst();
|
return effects.stream().filter(effect -> effect.test(stack)).findFirst().orElse(Effect.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Effect> getEffects(ItemStack stack, Pony pony) {
|
private Effect getEffects(ItemStack stack, Pony pony) {
|
||||||
return getDiet(pony.getObservedSpecies()).flatMap(diet -> diet.findEffect(stack)).or(() -> getEffects(stack));
|
return getDiet(pony).findEffect(stack).orElseGet(() -> getEffects(stack));
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Multiplier> getMultiplier(ItemStack stack, Pony pony) {
|
@Override
|
||||||
return getDiet(pony.getObservedSpecies()).flatMap(diet -> diet.findMultiplier(stack));
|
public TypedActionResult<ItemStack> startUsing(ItemStack stack, World world, PlayerEntity user, Hand hand) {
|
||||||
|
return initEdibility(stack, user)
|
||||||
|
? FoodPoisoningStatusEffect.apply(stack, user)
|
||||||
|
: TypedActionResult.fail(stack);
|
||||||
|
}
|
||||||
|
|
||||||
|
@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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void appendTooltip(ItemStack stack, @Nullable PlayerEntity user, List<Text> tooltip, TooltipContext context) {
|
||||||
|
if (initEdibility(stack, user)) {
|
||||||
|
Pony pony = Pony.of(user);
|
||||||
|
|
||||||
|
tooltip.add(Text.translatable("unicopia.diet.information").formatted(Formatting.DARK_PURPLE));
|
||||||
|
getEffects(stack, pony).appendTooltip(stack, tooltip, context);
|
||||||
|
getDiet(pony).appendTooltip(stack, user, tooltip, context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean initEdibility(ItemStack stack, LivingEntity user) {
|
||||||
|
ItemDuck item = (ItemDuck)stack.getItem();
|
||||||
|
item.resetFoodComponent();
|
||||||
|
return Pony.of(user).filter(pony -> {
|
||||||
|
DietProfile diet = getDiet(pony);
|
||||||
|
|
||||||
|
if (!stack.isFood() && pony.getObservedSpecies().hasIronGut()) {
|
||||||
|
diet.findEffect(stack)
|
||||||
|
.flatMap(Effect::foodComponent)
|
||||||
|
.or(() -> getEffects(stack).foodComponent())
|
||||||
|
.ifPresent(item::setFoodComponent);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (stack.isFood()) {
|
||||||
|
item.setFoodComponent(diet.getAdjustedFoodComponent(stack));
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}).isPresent();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.unicopia.diet;
|
package com.minelittlepony.unicopia.diet.affliction;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -9,19 +9,14 @@ import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
|
import net.minecraft.util.Formatting;
|
||||||
import net.minecraft.util.dynamic.Codecs;
|
import net.minecraft.util.dynamic.Codecs;
|
||||||
|
|
||||||
public interface Affliction {
|
public interface Affliction {
|
||||||
Text NO_EFFECT_TEXT = Text.of("No Effect");
|
|
||||||
Affliction EMPTY = new Affliction() {
|
Affliction EMPTY = new Affliction() {
|
||||||
@Override
|
@Override
|
||||||
public void afflict(PlayerEntity player, ItemStack stack) { }
|
public void afflict(PlayerEntity player, ItemStack stack) { }
|
||||||
|
|
||||||
@Override
|
|
||||||
public Text getName() {
|
|
||||||
return NO_EFFECT_TEXT;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AfflictionType<?> getType() {
|
public AfflictionType<?> getType() {
|
||||||
return AfflictionType.EMPTY;
|
return AfflictionType.EMPTY;
|
||||||
|
@ -30,11 +25,9 @@ public interface Affliction {
|
||||||
@Override
|
@Override
|
||||||
public void toBuffer(PacketByteBuf buffer) { }
|
public void toBuffer(PacketByteBuf buffer) { }
|
||||||
};
|
};
|
||||||
Codec<Affliction> CODEC = Codecs.xor(Codec.list(AfflictionType.CODEC)
|
Codec<Affliction> CODEC = Codecs.xor(AfflictionType.CODEC, Codec.list(AfflictionType.CODEC).xmap(
|
||||||
.mapResult(null)
|
|
||||||
.xmap(
|
|
||||||
afflictions -> {
|
afflictions -> {
|
||||||
afflictions.removeIf(f -> f.getType() == AfflictionType.EMPTY);
|
afflictions = afflictions.stream().filter(f -> !f.isEmpty()).toList();
|
||||||
return switch (afflictions.size()) {
|
return switch (afflictions.size()) {
|
||||||
case 0 -> EMPTY;
|
case 0 -> EMPTY;
|
||||||
case 1 -> afflictions.get(0);
|
case 1 -> afflictions.get(0);
|
||||||
|
@ -42,18 +35,24 @@ public interface Affliction {
|
||||||
};
|
};
|
||||||
},
|
},
|
||||||
affliction -> ((CompoundAffliction)affliction).afflictions
|
affliction -> ((CompoundAffliction)affliction).afflictions
|
||||||
), AfflictionType.CODEC).xmap(
|
)).xmap(
|
||||||
either -> either.left().or(either::right).get(),
|
either -> either.left().or(either::right).get(),
|
||||||
affliction -> affliction instanceof CompoundAffliction ? Either.left(affliction) : Either.right(affliction)
|
affliction -> affliction instanceof CompoundAffliction ? Either.left(affliction) : Either.right(affliction)
|
||||||
);
|
);
|
||||||
|
|
||||||
void afflict(PlayerEntity player, ItemStack stack);
|
void afflict(PlayerEntity player, ItemStack stack);
|
||||||
|
|
||||||
default void appendTooltip(List<Text> tooltip) {
|
default boolean isEmpty() {
|
||||||
tooltip.add(getName());
|
return getType() == AfflictionType.EMPTY;
|
||||||
}
|
}
|
||||||
|
|
||||||
Text getName();
|
default void appendTooltip(List<Text> tooltip) {
|
||||||
|
tooltip.add(Text.literal(" ").append(getName()).formatted(Formatting.DARK_GRAY));
|
||||||
|
}
|
||||||
|
|
||||||
|
default Text getName() {
|
||||||
|
return Text.translatable(getType().getTranslationKey());
|
||||||
|
}
|
||||||
|
|
||||||
AfflictionType<?> getType();
|
AfflictionType<?> getType();
|
||||||
|
|
|
@ -1,14 +1,16 @@
|
||||||
package com.minelittlepony.unicopia.diet;
|
package com.minelittlepony.unicopia.diet.affliction;
|
||||||
|
|
||||||
import com.google.gson.JsonObject;
|
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
import com.minelittlepony.unicopia.util.RegistryUtils;
|
import com.minelittlepony.unicopia.util.RegistryUtils;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.DataResult;
|
||||||
import com.mojang.serialization.JsonOps;
|
import com.mojang.serialization.JsonOps;
|
||||||
|
|
||||||
import net.minecraft.network.PacketByteBuf.PacketReader;
|
import net.minecraft.network.PacketByteBuf.PacketReader;
|
||||||
import net.minecraft.registry.Registry;
|
import net.minecraft.registry.Registry;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.JsonHelper;
|
||||||
|
import net.minecraft.util.Util;
|
||||||
import net.minecraft.util.dynamic.Codecs;
|
import net.minecraft.util.dynamic.Codecs;
|
||||||
|
|
||||||
public record AfflictionType<T extends Affliction>(Codec<T> codec, Identifier id, PacketReader<T> reader) {
|
public record AfflictionType<T extends Affliction>(Codec<T> codec, Identifier id, PacketReader<T> reader) {
|
||||||
|
@ -16,10 +18,11 @@ public record AfflictionType<T extends Affliction>(Codec<T> codec, Identifier id
|
||||||
public static final Registry<AfflictionType<?>> REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("affliction_type"), DEFAULT_ID);
|
public static final Registry<AfflictionType<?>> REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("affliction_type"), DEFAULT_ID);
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static final Codec<Affliction> CODEC = Codecs.JSON_ELEMENT.<Affliction>flatXmap(json -> {
|
public static final Codec<Affliction> CODEC = Codecs.JSON_ELEMENT.<Affliction>flatXmap(json -> {
|
||||||
JsonObject obj = json.getAsJsonObject();
|
if (!json.isJsonObject()) {
|
||||||
return Identifier.validate(obj.has("type") ? obj.get("type").getAsString() : AfflictionType.DEFAULT_ID).flatMap(type -> {
|
return DataResult.error(() -> "Not a JSON object");
|
||||||
return AfflictionType.REGISTRY.get(type).codec().parse(JsonOps.INSTANCE, json);
|
}
|
||||||
});
|
return Identifier.validate(JsonHelper.getString(JsonHelper.asObject(json, "affliction"), "type", AfflictionType.DEFAULT_ID))
|
||||||
|
.flatMap(type -> AfflictionType.REGISTRY.get(type).codec().parse(JsonOps.INSTANCE, json));
|
||||||
}, thing -> {
|
}, thing -> {
|
||||||
AfflictionType<?> type = thing.getType();
|
AfflictionType<?> type = thing.getType();
|
||||||
return ((Codec<Affliction>)type.codec()).encodeStart(JsonOps.INSTANCE, thing).map(json -> {
|
return ((Codec<Affliction>)type.codec()).encodeStart(JsonOps.INSTANCE, thing).map(json -> {
|
||||||
|
@ -33,12 +36,17 @@ public record AfflictionType<T extends Affliction>(Codec<T> codec, Identifier id
|
||||||
public static final AfflictionType<Affliction> EMPTY = register("empty", Codec.unit(Affliction.EMPTY), buffer -> Affliction.EMPTY);
|
public static final AfflictionType<Affliction> EMPTY = register("empty", Codec.unit(Affliction.EMPTY), buffer -> Affliction.EMPTY);
|
||||||
public static final AfflictionType<Affliction> MANY = register("many", CompoundAffliction.CODEC, CompoundAffliction::new);
|
public static final AfflictionType<Affliction> MANY = register("many", CompoundAffliction.CODEC, CompoundAffliction::new);
|
||||||
public static final AfflictionType<StatusEffectAffliction> APPLY_STATUS_EFFECT = register("apply_status_effect", StatusEffectAffliction.CODEC, StatusEffectAffliction::new);
|
public static final AfflictionType<StatusEffectAffliction> APPLY_STATUS_EFFECT = register("apply_status_effect", StatusEffectAffliction.CODEC, StatusEffectAffliction::new);
|
||||||
public static final AfflictionType<MultiplyHungerAffliction> MULTIPLY_HUNGER = register("multiply_hunger", MultiplyHungerAffliction.CODEC, MultiplyHungerAffliction::new);
|
public static final AfflictionType<LoseHungerAffliction> LOSE_HUNGER = register("lose_hunger", LoseHungerAffliction.CODEC, LoseHungerAffliction::new);
|
||||||
public static final AfflictionType<ClearLoveSicknessAffliction> CLEAR_LOVE_SICKNESS = register("clear_love_sickness", ClearLoveSicknessAffliction.CODEC, buffer -> ClearLoveSicknessAffliction.INSTANCE);
|
public static final AfflictionType<HealingAffliction> HEALING = register("healing", HealingAffliction.CODEC, HealingAffliction::new);
|
||||||
|
public static final AfflictionType<ClearLoveSicknessAffliction> CURE_LOVE_SICKNESS = register("cure_love_sickness", ClearLoveSicknessAffliction.CODEC, buffer -> ClearLoveSicknessAffliction.INSTANCE);
|
||||||
|
|
||||||
static <T extends Affliction> AfflictionType<T> register(String name, Codec<T> codec, PacketReader<T> reader) {
|
static <T extends Affliction> AfflictionType<T> register(String name, Codec<T> codec, PacketReader<T> reader) {
|
||||||
return Registry.register(REGISTRY, Unicopia.id(name), new AfflictionType<>(codec, Unicopia.id(name), reader));
|
return Registry.register(REGISTRY, Unicopia.id(name), new AfflictionType<>(codec, Unicopia.id(name), reader));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getTranslationKey() {
|
||||||
|
return Util.createTranslationKey("affliction", id());
|
||||||
|
}
|
||||||
|
|
||||||
public static void bootstrap() { }
|
public static void bootstrap() { }
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.unicopia.diet;
|
package com.minelittlepony.unicopia.diet.affliction;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.entity.effect.UEffects;
|
import com.minelittlepony.unicopia.entity.effect.UEffects;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
|
@ -6,15 +6,14 @@ import net.minecraft.entity.effect.StatusEffects;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.text.Text;
|
|
||||||
|
|
||||||
public final class ClearLoveSicknessAffliction implements Affliction {
|
final class ClearLoveSicknessAffliction implements Affliction {
|
||||||
public static final ClearLoveSicknessAffliction INSTANCE = new ClearLoveSicknessAffliction();
|
public static final ClearLoveSicknessAffliction INSTANCE = new ClearLoveSicknessAffliction();
|
||||||
public static final Codec<ClearLoveSicknessAffliction> CODEC = Codec.unit(INSTANCE);
|
public static final Codec<ClearLoveSicknessAffliction> CODEC = Codec.unit(INSTANCE);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public AfflictionType<?> getType() {
|
public AfflictionType<?> getType() {
|
||||||
return AfflictionType.CLEAR_LOVE_SICKNESS;
|
return AfflictionType.CURE_LOVE_SICKNESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -24,11 +23,6 @@ public final class ClearLoveSicknessAffliction implements Affliction {
|
||||||
player.removeStatusEffect(UEffects.FOOD_POISONING);
|
player.removeStatusEffect(UEffects.FOOD_POISONING);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public Text getName() {
|
|
||||||
return Text.literal("Love");
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toBuffer(PacketByteBuf buffer) {
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.unicopia.diet;
|
package com.minelittlepony.unicopia.diet.affliction;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
@ -32,6 +32,11 @@ class CompoundAffliction implements Affliction {
|
||||||
return AfflictionType.MANY;
|
return AfflictionType.MANY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isEmpty() {
|
||||||
|
return afflictions.isEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void appendTooltip(List<Text> tooltip) {
|
public void appendTooltip(List<Text> tooltip) {
|
||||||
afflictions.forEach(i -> i.appendTooltip(tooltip));
|
afflictions.forEach(i -> i.appendTooltip(tooltip));
|
|
@ -0,0 +1,39 @@
|
||||||
|
package com.minelittlepony.unicopia.diet.affliction;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
public HealingAffliction(PacketByteBuf buffer) {
|
||||||
|
this(buffer.readFloat());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
|
buffer.writeFloat(health);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AfflictionType<?> getType() {
|
||||||
|
return AfflictionType.HEALING;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afflict(PlayerEntity player, ItemStack stack) {
|
||||||
|
player.heal(health());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Text getName() {
|
||||||
|
return Text.translatable(getType().getTranslationKey(), health());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
package com.minelittlepony.unicopia.diet.affliction;
|
||||||
|
|
||||||
|
import com.mojang.serialization.Codec;
|
||||||
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.network.PacketByteBuf;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
public record LoseHungerAffliction(float multiplier) implements Affliction {
|
||||||
|
public static final Codec<LoseHungerAffliction> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
|
Codec.FLOAT.fieldOf("multiplier").forGetter(LoseHungerAffliction::multiplier)
|
||||||
|
).apply(instance, LoseHungerAffliction::new));
|
||||||
|
|
||||||
|
public LoseHungerAffliction(PacketByteBuf buffer) {
|
||||||
|
this(buffer.readFloat());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
|
buffer.writeFloat(multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AfflictionType<?> getType() {
|
||||||
|
return AfflictionType.LOSE_HUNGER;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void afflict(PlayerEntity player, ItemStack stack) {
|
||||||
|
var hunger = player.getHungerManager();
|
||||||
|
hunger.setFoodLevel((int)(hunger.getFoodLevel() * multiplier));
|
||||||
|
hunger.setSaturationLevel(hunger.getSaturationLevel() * multiplier);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Text getName() {
|
||||||
|
return Text.translatable(getType().getTranslationKey(), multiplier * 100);
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.unicopia.diet;
|
package com.minelittlepony.unicopia.diet.affliction;
|
||||||
|
|
||||||
import com.mojang.datafixers.util.Either;
|
import com.mojang.datafixers.util.Either;
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
|
@ -7,7 +7,7 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
import net.minecraft.network.PacketByteBuf;
|
import net.minecraft.network.PacketByteBuf;
|
||||||
import net.minecraft.util.dynamic.Codecs;
|
import net.minecraft.util.dynamic.Codecs;
|
||||||
|
|
||||||
public record Range(int min, int max) {
|
record Range(int min, int max) {
|
||||||
public static final Codec<Range> CODEC = Codecs.xor(
|
public static final Codec<Range> CODEC = Codecs.xor(
|
||||||
Codec.INT.xmap(value -> Range.of(value, -1), range -> range.min()),
|
Codec.INT.xmap(value -> Range.of(value, -1), range -> range.min()),
|
||||||
RecordCodecBuilder.create(instance -> instance.group(
|
RecordCodecBuilder.create(instance -> instance.group(
|
||||||
|
@ -29,11 +29,11 @@ public record Range(int min, int max) {
|
||||||
buffer.writeInt(max);
|
buffer.writeInt(max);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getTicks(int currentTicks) {
|
public int getClamped(int currentTicks, int multiplier) {
|
||||||
return clamp((min * 20) + currentTicks);
|
return clamp((min * multiplier) + currentTicks, multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int clamp(int value) {
|
public int clamp(int value, int multiplier) {
|
||||||
return max > 0 ? Math.min(value, max * 20) : value;
|
return max > 0 ? Math.min(value, max * multiplier) : value;
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.unicopia.diet;
|
package com.minelittlepony.unicopia.diet.affliction;
|
||||||
|
|
||||||
import com.mojang.serialization.Codec;
|
import com.mojang.serialization.Codec;
|
||||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||||
|
@ -15,7 +15,7 @@ import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.util.StringHelper;
|
import net.minecraft.util.StringHelper;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
public record StatusEffectAffliction(Identifier effect, Range seconds, Range amplifier, int chance) implements Affliction {
|
record StatusEffectAffliction(Identifier effect, Range seconds, Range amplifier, int chance) implements Affliction {
|
||||||
public static final Codec<StatusEffectAffliction> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
public static final Codec<StatusEffectAffliction> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||||
Identifier.CODEC.fieldOf("effect").forGetter(StatusEffectAffliction::effect),
|
Identifier.CODEC.fieldOf("effect").forGetter(StatusEffectAffliction::effect),
|
||||||
Range.CODEC.fieldOf("seconds").forGetter(StatusEffectAffliction::seconds),
|
Range.CODEC.fieldOf("seconds").forGetter(StatusEffectAffliction::seconds),
|
||||||
|
@ -27,6 +27,7 @@ public record StatusEffectAffliction(Identifier effect, Range seconds, Range amp
|
||||||
this(buffer.readIdentifier(), Range.of(buffer), Range.of(buffer), buffer.readInt());
|
this(buffer.readIdentifier(), Range.of(buffer), Range.of(buffer), buffer.readInt());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
public void toBuffer(PacketByteBuf buffer) {
|
public void toBuffer(PacketByteBuf buffer) {
|
||||||
buffer.writeIdentifier(effect);
|
buffer.writeIdentifier(effect);
|
||||||
seconds.toBuffer(buffer);
|
seconds.toBuffer(buffer);
|
||||||
|
@ -48,8 +49,8 @@ public record StatusEffectAffliction(Identifier effect, Range seconds, Range amp
|
||||||
float health = player.getHealth();
|
float health = player.getHealth();
|
||||||
StatusEffectInstance current = player.getStatusEffect(effect);
|
StatusEffectInstance current = player.getStatusEffect(effect);
|
||||||
player.addStatusEffect(new StatusEffectInstance(effect,
|
player.addStatusEffect(new StatusEffectInstance(effect,
|
||||||
seconds.getTicks(current == null ? 0 : current.getDuration()),
|
seconds.getClamped(current == null ? 0 : current.getDuration(), 20),
|
||||||
amplifier.getTicks(current == null ? 0 : current.getAmplifier())
|
amplifier.getClamped(current == null ? 0 : current.getAmplifier(), 1)
|
||||||
));
|
));
|
||||||
// keep original health
|
// keep original health
|
||||||
if (effect.getAttributeModifiers().containsKey(EntityAttributes.GENERIC_MAX_HEALTH)) {
|
if (effect.getAttributeModifiers().containsKey(EntityAttributes.GENERIC_MAX_HEALTH)) {
|
||||||
|
@ -64,7 +65,7 @@ public record StatusEffectAffliction(Identifier effect, Range seconds, Range amp
|
||||||
MutableText text = effect.getName().copy();
|
MutableText text = effect.getName().copy();
|
||||||
|
|
||||||
if (amplifier.min() > 0) {
|
if (amplifier.min() > 0) {
|
||||||
text = Text.translatable("potion.withAmplifier", text, Text.translatable("potion.potency." + (amplifier.min() * 20)));
|
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));
|
||||||
|
@ -73,6 +74,6 @@ public record StatusEffectAffliction(Identifier effect, Range seconds, Range amp
|
||||||
text = Text.translatable("potion.withChance", chance, text);
|
text = Text.translatable("potion.withChance", chance, text);
|
||||||
}
|
}
|
||||||
return (Text)text;
|
return (Text)text;
|
||||||
}).orElse(Text.of("No Effect"));
|
}).orElse(EMPTY.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
16
src/main/java/com/minelittlepony/unicopia/item/ItemDuck.java
Normal file
16
src/main/java/com/minelittlepony/unicopia/item/ItemDuck.java
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package com.minelittlepony.unicopia.item;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.entity.ItemImpl;
|
||||||
|
import net.minecraft.item.*;
|
||||||
|
|
||||||
|
public interface ItemDuck extends ItemConvertible, ItemImpl.TickableItem {
|
||||||
|
void setFoodComponent(FoodComponent food);
|
||||||
|
|
||||||
|
Optional<FoodComponent> getOriginalFoodComponent();
|
||||||
|
|
||||||
|
default void resetFoodComponent() {
|
||||||
|
setFoodComponent(getOriginalFoodComponent().orElse(null));
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
package com.minelittlepony.unicopia.item.toxin;
|
package com.minelittlepony.unicopia.item;
|
||||||
|
|
||||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||||
import net.minecraft.entity.effect.StatusEffects;
|
import net.minecraft.entity.effect.StatusEffects;
|
|
@ -12,7 +12,6 @@ import com.minelittlepony.unicopia.item.cloud.CloudBedItem;
|
||||||
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
|
||||||
import com.minelittlepony.unicopia.item.group.ItemGroupRegistry;
|
import com.minelittlepony.unicopia.item.group.ItemGroupRegistry;
|
||||||
import com.minelittlepony.unicopia.item.group.UItemGroups;
|
import com.minelittlepony.unicopia.item.group.UItemGroups;
|
||||||
import com.minelittlepony.unicopia.item.toxin.UFoodComponents;
|
|
||||||
import com.terraformersmc.terraform.boat.api.TerraformBoatType;
|
import com.terraformersmc.terraform.boat.api.TerraformBoatType;
|
||||||
import com.terraformersmc.terraform.boat.api.TerraformBoatTypeRegistry;
|
import com.terraformersmc.terraform.boat.api.TerraformBoatTypeRegistry;
|
||||||
import com.terraformersmc.terraform.boat.api.item.TerraformBoatItemHelper;
|
import com.terraformersmc.terraform.boat.api.item.TerraformBoatItemHelper;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import com.minelittlepony.unicopia.entity.Living;
|
||||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.item.group.MultiItem;
|
import com.minelittlepony.unicopia.item.group.MultiItem;
|
||||||
import com.minelittlepony.unicopia.item.toxin.*;
|
|
||||||
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
|
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.util.TraceHelper;
|
import com.minelittlepony.unicopia.util.TraceHelper;
|
||||||
|
@ -36,7 +35,7 @@ import net.minecraft.registry.Registries;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.event.GameEvent;
|
import net.minecraft.world.event.GameEvent;
|
||||||
|
|
||||||
public class ZapAppleItem extends Item implements ChameleonItem, ToxicHolder, MultiItem {
|
public class ZapAppleItem extends Item implements ChameleonItem, MultiItem {
|
||||||
public ZapAppleItem(Settings settings) {
|
public ZapAppleItem(Settings settings) {
|
||||||
super(settings);
|
super(settings);
|
||||||
}
|
}
|
||||||
|
@ -117,12 +116,6 @@ public class ZapAppleItem extends Item implements ChameleonItem, ToxicHolder, Mu
|
||||||
return hasAppearance(stack) ? getAppearanceStack(stack).getName() : super.getName(stack);
|
return hasAppearance(stack) ? getAppearanceStack(stack).getName() : super.getName(stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
@Override
|
|
||||||
public Toxic getToxic(ItemStack stack, LivingEntity entity) {
|
|
||||||
return hasAppearance(stack) ? Toxic.SEVERE_INNERT : Toxics.FORAGE_EDIBLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Rarity getRarity(ItemStack stack) {
|
public Rarity getRarity(ItemStack stack) {
|
||||||
if (hasAppearance(stack)) {
|
if (hasAppearance(stack)) {
|
||||||
|
|
|
@ -1,12 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.toxin;
|
|
||||||
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
|
|
||||||
public interface Affliction {
|
|
||||||
void afflict(PlayerEntity player, ItemStack stack);
|
|
||||||
|
|
||||||
interface Predicate {
|
|
||||||
boolean test(PlayerEntity player, ItemStack stack);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.toxin;
|
|
||||||
|
|
||||||
import java.util.*;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.Race;
|
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
|
||||||
import net.minecraft.client.item.TooltipContext;
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
|
|
||||||
public record Ailment (
|
|
||||||
Toxicity toxicity,
|
|
||||||
Toxin effect
|
|
||||||
) {
|
|
||||||
public static final Ailment INNERT = of(Toxicity.SAFE, Toxin.INNERT);
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static Ailment of(Toxicity toxicity, Toxin effect) {
|
|
||||||
return new Ailment(toxicity, effect);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void appendTooltip(List<Text> tooltip, TooltipContext context) {
|
|
||||||
tooltip.add(toxicity().getTooltip());
|
|
||||||
if (context.isAdvanced()) {
|
|
||||||
effect().appendTooltip(tooltip);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public interface Set {
|
|
||||||
Set EMPTY = e -> Optional.empty();
|
|
||||||
|
|
||||||
Optional<Ailment> get(LivingEntity entity);
|
|
||||||
|
|
||||||
static Ailment.Set of(Ailment def, Map<Race, Ailment> map) {
|
|
||||||
if (map.isEmpty()) {
|
|
||||||
return of(def);
|
|
||||||
}
|
|
||||||
return entity -> Optional.of(entity instanceof PlayerEntity player ? map.getOrDefault(Pony.of(player).getObservedSpecies(), def) : def);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Ailment.Set of(Ailment ailment) {
|
|
||||||
final Optional<Ailment> value = Optional.of(ailment);
|
|
||||||
return entity -> value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.toxin;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.entity.ItemImpl;
|
|
||||||
|
|
||||||
import net.minecraft.item.*;
|
|
||||||
|
|
||||||
public interface ItemDuck extends ItemConvertible, ToxicHolder, ItemImpl.TickableItem {
|
|
||||||
void setFoodComponent(FoodComponent food);
|
|
||||||
}
|
|
|
@ -1,108 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.toxin;
|
|
||||||
|
|
||||||
import static com.minelittlepony.unicopia.item.toxin.Toxicity.FAIR;
|
|
||||||
import static com.minelittlepony.unicopia.item.toxin.Toxicity.SEVERE;
|
|
||||||
import java.util.*;
|
|
||||||
import java.util.function.Function;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.Race;
|
|
||||||
import com.minelittlepony.unicopia.entity.effect.FoodPoisoningStatusEffect;
|
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
|
||||||
import net.minecraft.client.item.TooltipContext;
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.item.BlockItem;
|
|
||||||
import net.minecraft.item.FoodComponent;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.Hand;
|
|
||||||
import net.minecraft.util.TypedActionResult;
|
|
||||||
import net.minecraft.util.UseAction;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
public record Toxic (
|
|
||||||
Optional<UseAction> useAction,
|
|
||||||
Function<LivingEntity, Optional<FoodComponent>> food,
|
|
||||||
Ailment.Set ailment
|
|
||||||
) {
|
|
||||||
public static final Toxic EMPTY = new Toxic(Optional.empty(), entity -> Optional.empty(), Ailment.Set.EMPTY);
|
|
||||||
/**
|
|
||||||
* Default for all food that doesn't have a mapping
|
|
||||||
*/
|
|
||||||
@Deprecated
|
|
||||||
public static final Toxic DEFAULT = new Toxic.Builder(Ailment.INNERT)
|
|
||||||
.with(Race.CHANGELING, new Ailment(FAIR, Toxin.LOVE_SICKNESS))
|
|
||||||
.with(Race.SEAPONY, new Ailment(FAIR, Toxin.FOOD_POISONING))
|
|
||||||
.build();
|
|
||||||
|
|
||||||
public static final Toxic SEVERE_INNERT = new Builder(new Ailment(SEVERE, Toxin.INNERT)).build();
|
|
||||||
|
|
||||||
public void appendTooltip(PlayerEntity player, List<Text> tooltip, TooltipContext context) {
|
|
||||||
ailment.get(player).ifPresent(ailment -> ailment.appendTooltip(tooltip, context));
|
|
||||||
}
|
|
||||||
|
|
||||||
public TypedActionResult<ItemStack> startUsing(ItemStack stack, World world, PlayerEntity user, Hand hand) {
|
|
||||||
if (stack.getItem() instanceof BlockItem && ailment().get(user).isPresent() && !Pony.of(user).getObservedSpecies().hasIronGut()) {
|
|
||||||
return TypedActionResult.fail(stack);
|
|
||||||
}
|
|
||||||
return FoodPoisoningStatusEffect.apply(stack, user);
|
|
||||||
}
|
|
||||||
|
|
||||||
public void finishUsing(ItemStack stack, World world, LivingEntity entity) {
|
|
||||||
if (entity instanceof PlayerEntity player) {
|
|
||||||
ailment.get(entity).ifPresent(ailment -> ailment.effect().afflict(player, stack));
|
|
||||||
}
|
|
||||||
if (stack.isFood() || stack.getUseAction() == UseAction.DRINK) {
|
|
||||||
Pony.of(entity).ifPresent(pony -> pony.onEat(stack));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public static class Builder {
|
|
||||||
private final Ailment def;
|
|
||||||
private final Map<Race, Ailment> overrides = new HashMap<>();
|
|
||||||
private Optional<UseAction> action = Optional.of(UseAction.EAT);
|
|
||||||
private final Map<Race, FoodComponent> components = new HashMap<>();
|
|
||||||
private Optional<FoodComponent> component = Optional.empty();
|
|
||||||
|
|
||||||
public Builder(Ailment def) {
|
|
||||||
this.def = def;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder action(UseAction action) {
|
|
||||||
this.action = Optional.of(action);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder food(FoodComponent food) {
|
|
||||||
component = Optional.ofNullable(food);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder food(Race race, FoodComponent food) {
|
|
||||||
components.put(race, food);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder with(Race race, Ailment ailment) {
|
|
||||||
overrides.put(race, ailment);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Builder with(Ailment ailment, Race... races) {
|
|
||||||
for (Race race : races) {
|
|
||||||
overrides.put(race, ailment);
|
|
||||||
}
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Toxic build() {
|
|
||||||
return new Toxic(action, entity -> {
|
|
||||||
if (entity instanceof PlayerEntity player) {
|
|
||||||
return Optional.ofNullable(components.get(Pony.of(player).getObservedSpecies())).or(() -> component);
|
|
||||||
}
|
|
||||||
return component;
|
|
||||||
}, Ailment.Set.of(def, overrides));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.toxin;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.item.*;
|
|
||||||
|
|
||||||
public interface ToxicHolder {
|
|
||||||
Toxic getToxic(ItemStack stack, @Nullable LivingEntity entity);
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.toxin;
|
|
||||||
|
|
||||||
import net.minecraft.item.Item;
|
|
||||||
import net.minecraft.registry.tag.TagKey;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public record ToxicRegistryEntry (
|
|
||||||
Toxic value,
|
|
||||||
TagKey<Item> tag
|
|
||||||
) {
|
|
||||||
|
|
||||||
public boolean matches(Item item) {
|
|
||||||
return item.getRegistryEntry().isIn(tag);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,47 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.toxin;
|
|
||||||
|
|
||||||
import java.util.Arrays;
|
|
||||||
import java.util.Locale;
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.function.Function;
|
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.Formatting;
|
|
||||||
import net.minecraft.util.StringIdentifiable;
|
|
||||||
|
|
||||||
public enum Toxicity implements StringIdentifiable {
|
|
||||||
SAFE(Formatting.GRAY),
|
|
||||||
MILD(Formatting.DARK_AQUA),
|
|
||||||
FAIR(Formatting.DARK_BLUE),
|
|
||||||
SEVERE(Formatting.DARK_PURPLE),
|
|
||||||
LETHAL(Formatting.RED);
|
|
||||||
|
|
||||||
private static final Map<String, Toxicity> REGISTRY = Arrays.stream(values()).collect(Collectors.toMap(Toxicity::name, Function.identity()));
|
|
||||||
@SuppressWarnings("deprecation")
|
|
||||||
public static final Codec<Toxicity> CODEC = StringIdentifiable.createCodec(Toxicity::values);
|
|
||||||
|
|
||||||
private final Formatting color;
|
|
||||||
private final String name = name().toLowerCase(Locale.ROOT);
|
|
||||||
|
|
||||||
Toxicity(Formatting color) {
|
|
||||||
this.color = color;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getTranslationKey() {
|
|
||||||
return String.format("toxicity.%s.name", name().toLowerCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
public Text getTooltip() {
|
|
||||||
return Text.translatable(getTranslationKey()).formatted(color);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static Toxicity byName(String name) {
|
|
||||||
return REGISTRY.get(name.toUpperCase());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String asString() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,65 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.toxin;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.*;
|
|
||||||
import com.minelittlepony.unicopia.util.RegistryUtils;
|
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.item.FoodComponent;
|
|
||||||
import net.minecraft.registry.Registry;
|
|
||||||
|
|
||||||
import static com.minelittlepony.unicopia.item.toxin.Toxicity.*;
|
|
||||||
import static com.minelittlepony.unicopia.item.toxin.Ailment.*;
|
|
||||||
import static com.minelittlepony.unicopia.item.toxin.Toxin.*;
|
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public interface Toxics {
|
|
||||||
Registry<ToxicRegistryEntry> REGISTRY = RegistryUtils.createSimple(Unicopia.id("toxic"));
|
|
||||||
Toxic FORAGE_EDIBLE = register("forage_edible", new Toxic.Builder(Ailment.INNERT).food(UFoodComponents.RANDOM_FOLIAGE).with(Race.HUMAN, of(LETHAL, FOOD_POISONING)).with(Race.CHANGELING, of(FAIR, LOVE_SICKNESS)).with(Race.SEAPONY, of(FAIR, FOOD_POISONING)));
|
|
||||||
|
|
||||||
static void bootstrap() {
|
|
||||||
register("forage_edible_filling", new Toxic.Builder(Ailment.INNERT).food(UFoodComponents.RANDOM_FOLIAGE_FILLING).with(Race.CHANGELING, of(FAIR, LOVE_SICKNESS)).with(Race.SEAPONY, of(FAIR, FOOD_POISONING)));
|
|
||||||
register("forage_risky", new Toxic.Builder(of(FAIR, FOOD_POISONING.withChance(20))).food(UFoodComponents.RANDOM_FOLIAGE));
|
|
||||||
register("forage_moderate", new Toxic.Builder(of(MILD, FOOD_POISONING)).food(UFoodComponents.RANDOM_FOLIAGE));
|
|
||||||
register("forage_dangerous", new Toxic.Builder(of(SEVERE, FOOD_POISONING)).food(UFoodComponents.RANDOM_FOLIAGE));
|
|
||||||
register("forage_nauseating", new Toxic.Builder(of(SAFE, FOOD_POISONING.and(WEAKNESS.withChance(30)))).food(UFoodComponents.RANDOM_FOLIAGE));
|
|
||||||
register("forage_radioactive", new Toxic.Builder(of(SAFE, FOOD_POISONING.and(GLOWING.withChance(30)))).food(UFoodComponents.RANDOM_FOLIAGE));
|
|
||||||
register("forage_prickly", new Toxic.Builder(of(SAFE, INSTANT_DAMAGE.withChance(30))).food(UFoodComponents.RANDOM_FOLIAGE).with(Ailment.INNERT, Race.HIPPOGRIFF, Race.KIRIN));
|
|
||||||
register("forage_strengthening", new Toxic.Builder(of(SEVERE, STRENGTH.and(FOOD_POISONING))).food(UFoodComponents.RANDOM_FOLIAGE).with(Race.KIRIN, Ailment.INNERT));
|
|
||||||
register("forage_severely_nauseating", new Toxic.Builder(of(SEVERE, FOOD_POISONING.and(WEAKNESS))).food(UFoodComponents.RANDOM_FOLIAGE));
|
|
||||||
register("forage_blinding", new Toxic.Builder(of(SEVERE, BLINDNESS.and(FOOD_POISONING))).food(UFoodComponents.RANDOM_FOLIAGE).with(Race.KIRIN, Ailment.INNERT));
|
|
||||||
register("forage_severely_prickly", new Toxic.Builder(of(SEVERE, FOOD_POISONING.and(INSTANT_DAMAGE))).food(UFoodComponents.RANDOM_FOLIAGE).with(Race.KIRIN, Ailment.INNERT));
|
|
||||||
register("raw_meat", new Toxic.Builder(of(SEVERE, FOOD_POISONING.withChance(5).and(CHANCE_OF_POISON))).with(Ailment.INNERT, Race.HUMAN, Race.CHANGELING, Race.KIRIN).with(of(MILD, FOOD_POISONING), Race.BAT));
|
|
||||||
register("rotten_meat", new Toxic.Builder(of(SEVERE, STRONG_FOOD_POISONING)).with(Ailment.INNERT, Race.HUMAN, Race.CHANGELING).with(of(MILD, FOOD_POISONING), Race.BAT));
|
|
||||||
register("cooked_meat", new Toxic.Builder(of(FAIR, FOOD_POISONING)).with(Ailment.INNERT, Race.HUMAN, Race.CHANGELING, Race.BAT, Race.KIRIN).with(of(MILD, FOOD_POISONING), Race.HIPPOGRIFF));
|
|
||||||
register("raw_fish", new Toxic.Builder(of(FAIR, FOOD_POISONING.and(CHANCE_OF_POISON))).with(Ailment.INNERT, Race.HUMAN, Race.HIPPOGRIFF, Race.SEAPONY, Race.ALICORN).with(of(MILD, FOOD_POISONING), Race.PEGASUS).with(of(FAIR, LOVE_SICKNESS), Race.CHANGELING));
|
|
||||||
register("cooked_fish", new Toxic.Builder(of(MILD, FOOD_POISONING)).with(Ailment.INNERT, Race.HUMAN, Race.PEGASUS, Race.HIPPOGRIFF, Race.SEAPONY, Race.ALICORN).with(of(FAIR, LOVE_SICKNESS), Race.CHANGELING));
|
|
||||||
register("raw_insect", new Toxic.Builder(of(LETHAL, FOOD_POISONING)).food(UFoodComponents.INSECTS).with(Ailment.INNERT, Race.CHANGELING).with(of(MILD, WEAK_FOOD_POISONING), Race.BAT));
|
|
||||||
register("cooked_insect", new Toxic.Builder(of(LETHAL, FOOD_POISONING)).food(UFoodComponents.INSECTS).with(Ailment.INNERT, Race.CHANGELING, Race.KIRIN, Race.BAT));
|
|
||||||
register("love", new Toxic.Builder(Ailment.INNERT).with(of(Toxicity.SAFE, Toxin.LOVE_CONSUMPTION), Race.CHANGELING));
|
|
||||||
register("bat_ponys_delight", new Toxic.Builder(Ailment.INNERT).with(of(Toxicity.SAFE, Toxin.BAT_PONY_INTOXICATION), Race.BAT));
|
|
||||||
register("raw_sea_vegitable", new Toxic.Builder(Ailment.INNERT).food(Race.SEAPONY, UFoodComponents.RANDOM_FOLIAGE));
|
|
||||||
register("cooked_sea_vegitable", new Toxic.Builder(Ailment.INNERT).food(Race.SEAPONY, UFoodComponents.RANDOM_FOLIAGE_FILLING));
|
|
||||||
register("shells", new Toxic.Builder(Ailment.INNERT).food(Race.SEAPONY, UFoodComponents.SHELL));
|
|
||||||
register("shelly", new Toxic.Builder(Ailment.INNERT).food(Race.SEAPONY, UFoodComponents.SHELLY));
|
|
||||||
register("pinecone", new Toxic.Builder(of(Toxicity.SAFE, Toxin.healing(1))).with(Ailment.INNERT, Race.HUMAN).with(of(Toxicity.SAFE, Toxin.healing(3)), Race.HIPPOGRIFF));
|
|
||||||
}
|
|
||||||
|
|
||||||
static Toxic register(String name, Toxic.Builder builder) {
|
|
||||||
return Registry.register(REGISTRY, Unicopia.id(name), new ToxicRegistryEntry(builder.build(), UTags.item("food_types/" + name))).value();
|
|
||||||
}
|
|
||||||
|
|
||||||
static Toxic lookup(ItemDuck item, @Nullable LivingEntity entity) {
|
|
||||||
@Nullable FoodComponent food = item.asItem().getFoodComponent();
|
|
||||||
return REGISTRY.stream()
|
|
||||||
.filter(i -> i.matches(item.asItem()))
|
|
||||||
.map(ToxicRegistryEntry::value)
|
|
||||||
.map(t -> {
|
|
||||||
if (food == null) {
|
|
||||||
t.food().apply(entity).ifPresent(item::setFoodComponent);
|
|
||||||
}
|
|
||||||
return t;
|
|
||||||
}).findFirst().orElse(food == null ? Toxic.EMPTY : Toxic.DEFAULT);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,180 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.item.toxin;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.entity.effect.UEffects;
|
|
||||||
import net.minecraft.entity.attribute.EntityAttributes;
|
|
||||||
import net.minecraft.entity.effect.StatusEffect;
|
|
||||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
|
||||||
import net.minecraft.entity.effect.StatusEffects;
|
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
import net.minecraft.item.FoodComponent;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.text.MutableText;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.util.StringHelper;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
|
|
||||||
public interface Toxin extends Affliction {
|
|
||||||
Toxin INNERT = of(Text.of("No Effect"), (player, stack) -> {});
|
|
||||||
@Deprecated
|
|
||||||
Toxin INSTANT_DAMAGE = of(StatusEffects.INSTANT_DAMAGE, 1, 0);
|
|
||||||
@Deprecated
|
|
||||||
Toxin GLOWING = of(StatusEffects.GLOWING, 15, 0);
|
|
||||||
@Deprecated
|
|
||||||
Toxin WEAKNESS = of(StatusEffects.WEAKNESS, 200, 1);
|
|
||||||
@Deprecated
|
|
||||||
Toxin STRENGTH = of(StatusEffects.STRENGTH, 30, 0);
|
|
||||||
@Deprecated
|
|
||||||
Toxin BLINDNESS = of(StatusEffects.BLINDNESS, 30, 0);
|
|
||||||
@Deprecated
|
|
||||||
Toxin CHANCE_OF_POISON = of(StatusEffects.POISON, 45, 2).withChance(80);
|
|
||||||
@Deprecated
|
|
||||||
Toxin FOOD_POISONING = of(UEffects.FOOD_POISONING, 100, 2);
|
|
||||||
@Deprecated
|
|
||||||
Toxin WEAK_FOOD_POISONING = of(UEffects.FOOD_POISONING, 50, 1);
|
|
||||||
@Deprecated
|
|
||||||
Toxin STRONG_FOOD_POISONING = of(UEffects.FOOD_POISONING, 400, 3);
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
Toxin LOVE_SICKNESS = of(Text.of("Love Sickness "), (player, stack) -> {
|
|
||||||
FoodComponent food = stack.getItem().getFoodComponent();
|
|
||||||
player.getHungerManager().add(-food.getHunger()/2, -food.getSaturationModifier()/2);
|
|
||||||
}).and(FOOD_POISONING).and(WEAKNESS);
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
Toxin LOVE_CONSUMPTION = of(Text.literal("Love"), (player, stack) -> {
|
|
||||||
player.heal(stack.isFood() ? stack.getItem().getFoodComponent().getHunger() : 1);
|
|
||||||
player.removeStatusEffect(StatusEffects.NAUSEA);
|
|
||||||
player.removeStatusEffect(UEffects.FOOD_POISONING);
|
|
||||||
});
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
Toxin BAT_PONY_INTOXICATION = Toxin.of(StatusEffects.HEALTH_BOOST, 30, 60, 2, 6)
|
|
||||||
.and(Toxin.of(StatusEffects.JUMP_BOOST, 30, 60, 1, 6))
|
|
||||||
.and(Toxin.of(StatusEffects.SPEED, 30, 30, 1, 6))
|
|
||||||
.and(Toxin.of(StatusEffects.REGENERATION, 3, 30, 3, 6));
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
static Toxin healing(int hearts) {
|
|
||||||
return of(Text.literal("Healing " + hearts + " Hearts"), (player, stack) -> player.heal(hearts));
|
|
||||||
}
|
|
||||||
|
|
||||||
default void appendTooltip(List<Text> tooltip) {
|
|
||||||
tooltip.add(getName());
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
default Toxin withChance(int max) {
|
|
||||||
return Predicate.of(Text.of("1 in " + max + " chance of "), (player, stack) -> player.getWorld().random.nextInt(max) == 0).then(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
Text getName();
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
default Toxin and(Toxin other) {
|
|
||||||
Toxin self = this;
|
|
||||||
return new Toxin() {
|
|
||||||
@Override
|
|
||||||
public void afflict(PlayerEntity player, ItemStack stack) {
|
|
||||||
self.afflict(player, stack);
|
|
||||||
other.afflict(player, stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void appendTooltip(List<Text> tooltip) {
|
|
||||||
self.appendTooltip(tooltip);
|
|
||||||
other.appendTooltip(tooltip);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Text getName() {
|
|
||||||
return self.getName().copy().append(" + ").append(other.getName());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static Toxin of(Text name, Affliction affliction) {
|
|
||||||
return new Toxin() {
|
|
||||||
@Override
|
|
||||||
public void afflict(PlayerEntity player, ItemStack stack) {
|
|
||||||
affliction.afflict(player, stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Text getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
static Toxin of(StatusEffect effect, int seconds, int amplifier) {
|
|
||||||
return of(effect, seconds, -1, amplifier, -1);
|
|
||||||
}
|
|
||||||
|
|
||||||
static Toxin of(StatusEffect effect, int seconds, int maxSeconds, int amplifier, int maxAmplifier) {
|
|
||||||
final int ticks = seconds * 20;
|
|
||||||
final int maxTicks = maxSeconds * 20;
|
|
||||||
|
|
||||||
MutableText text = effect.getName().copy();
|
|
||||||
|
|
||||||
if (amplifier > 0) {
|
|
||||||
text = Text.translatable("potion.withAmplifier", text, Text.translatable("potion.potency." + amplifier));
|
|
||||||
}
|
|
||||||
|
|
||||||
text = Text.translatable("potion.withDuration", text, StringHelper.formatTicks(ticks));
|
|
||||||
|
|
||||||
return of(text, (player, stack) -> {
|
|
||||||
float health = player.getHealth();
|
|
||||||
StatusEffectInstance current = player.getStatusEffect(effect);
|
|
||||||
int t = applyLimit(ticks + (current == null ? 0 : current.getDuration()), maxTicks);
|
|
||||||
int a = applyLimit(amplifier + (current == null ? 0 : current.getAmplifier()), maxAmplifier);
|
|
||||||
player.addStatusEffect(new StatusEffectInstance(effect, t, a));
|
|
||||||
// keep original health
|
|
||||||
if (effect.getAttributeModifiers().containsKey(EntityAttributes.GENERIC_MAX_HEALTH)) {
|
|
||||||
player.setHealth(MathHelper.clamp(health, 0, player.getMaxHealth()));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static int applyLimit(int value, int max) {
|
|
||||||
return max > 0 ? Math.min(value, max) : value;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface Predicate {
|
|
||||||
static Predicate of(Text name, Affliction.Predicate predicate) {
|
|
||||||
return new Predicate() {
|
|
||||||
@Override
|
|
||||||
public boolean test(PlayerEntity player, ItemStack stack) {
|
|
||||||
return predicate.test(player, stack);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Text getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
boolean test(PlayerEntity player, ItemStack stack);
|
|
||||||
|
|
||||||
Text getName();
|
|
||||||
|
|
||||||
default Toxin then(Toxin toxin) {
|
|
||||||
return new Toxin() {
|
|
||||||
@Override
|
|
||||||
public void afflict(PlayerEntity player, ItemStack stack) {
|
|
||||||
if (test(player, stack)) {
|
|
||||||
toxin.afflict(player, stack);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Text getName() {
|
|
||||||
return Predicate.this.getName().copy().append(toxin.getName());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -5,24 +5,21 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.item.toxin.ToxicHolder;
|
|
||||||
import com.minelittlepony.unicopia.server.world.WaterLoggingManager;
|
import com.minelittlepony.unicopia.server.world.WaterLoggingManager;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.item.BlockItem;
|
import net.minecraft.item.BlockItem;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemPlacementContext;
|
import net.minecraft.item.ItemPlacementContext;
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.util.UseAction;
|
|
||||||
|
|
||||||
@Mixin(BlockItem.class)
|
@Mixin(BlockItem.class)
|
||||||
abstract class MixinBlockItem extends Item implements ToxicHolder {
|
abstract class MixinBlockItem extends Item {
|
||||||
MixinBlockItem() {super(null); }
|
MixinBlockItem() {super(null); }
|
||||||
|
|
||||||
@Override
|
/*@Override
|
||||||
public UseAction getUseAction(ItemStack stack) {
|
public UseAction getUseAction(ItemStack stack) {
|
||||||
return getToxic(stack, null).useAction().orElseGet(() -> super.getUseAction(stack));
|
return PonyDiets.getinstance().getUseAction(stack).orElseGet(() -> super.getUseAction(stack));
|
||||||
}
|
}*/
|
||||||
|
|
||||||
@Inject(method = "getPlacementState", at = @At("RETURN"), cancellable = true)
|
@Inject(method = "getPlacementState", at = @At("RETURN"), cancellable = true)
|
||||||
private void onGetPlacementState(ItemPlacementContext context, CallbackInfoReturnable<BlockState> info) {
|
private void onGetPlacementState(ItemPlacementContext context, CallbackInfoReturnable<BlockState> info) {
|
||||||
|
|
|
@ -2,26 +2,26 @@ package com.minelittlepony.unicopia.mixin;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Optional;
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.Mutable;
|
import org.spongepowered.asm.mixin.Mutable;
|
||||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.minelittlepony.unicopia.diet.DietView;
|
||||||
import com.minelittlepony.unicopia.entity.ItemImpl;
|
import com.minelittlepony.unicopia.entity.ItemImpl;
|
||||||
import com.minelittlepony.unicopia.entity.ItemImpl.GroundTickCallback;
|
import com.minelittlepony.unicopia.entity.ItemImpl.GroundTickCallback;
|
||||||
import com.minelittlepony.unicopia.item.toxin.*;
|
import com.minelittlepony.unicopia.item.ItemDuck;
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
|
||||||
import net.minecraft.item.FoodComponent;
|
import net.minecraft.item.FoodComponent;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.item.Item;
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
|
|
||||||
@Mixin(Item.class)
|
@Mixin(Item.class)
|
||||||
abstract class MixinItem implements ItemDuck {
|
abstract class MixinItem implements ItemDuck, DietView.Holder {
|
||||||
private final List<ItemImpl.GroundTickCallback> tickCallbacks = new ArrayList<>();
|
private final List<ItemImpl.GroundTickCallback> tickCallbacks = new ArrayList<>();
|
||||||
private final Supplier<FoodComponent> originalFoodComponent = Suppliers.memoize(((Item)(Object)this)::getFoodComponent);
|
private final Supplier<Optional<FoodComponent>> originalFoodComponent = Suppliers.memoize(() -> {
|
||||||
|
return Optional.ofNullable(((Item)(Object)this).getFoodComponent());
|
||||||
|
});
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public List<GroundTickCallback> getCallbacks() {
|
public List<GroundTickCallback> getCallbacks() {
|
||||||
|
@ -34,10 +34,7 @@ abstract class MixinItem implements ItemDuck {
|
||||||
public abstract void setFoodComponent(FoodComponent food);
|
public abstract void setFoodComponent(FoodComponent food);
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Toxic getToxic(ItemStack stack, @Nullable LivingEntity entity) {
|
public Optional<FoodComponent> getOriginalFoodComponent() {
|
||||||
if (entity != null) {
|
return originalFoodComponent.get();
|
||||||
setFoodComponent(originalFoodComponent.get());
|
|
||||||
}
|
|
||||||
return Toxics.lookup(this, entity);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,8 +5,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.item.toxin.ToxicHolder;
|
import com.minelittlepony.unicopia.diet.DietView;
|
||||||
|
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
@ -20,7 +19,7 @@ abstract class MixinItemStack {
|
||||||
@Inject(method = "use", at = @At("HEAD"), cancellable = true)
|
@Inject(method = "use", at = @At("HEAD"), cancellable = true)
|
||||||
private void onUse(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable<TypedActionResult<ItemStack>> info) {
|
private void onUse(World world, PlayerEntity user, Hand hand, CallbackInfoReturnable<TypedActionResult<ItemStack>> info) {
|
||||||
ItemStack self = (ItemStack)(Object)this;
|
ItemStack self = (ItemStack)(Object)this;
|
||||||
TypedActionResult<ItemStack> result = ((ToxicHolder)self.getItem()).getToxic(self, user).startUsing(self, world, user, hand);
|
TypedActionResult<ItemStack> result = ((DietView.Holder)self.getItem()).getDiets(self).startUsing(self, world, user, hand);
|
||||||
if (result.getResult() != ActionResult.PASS) {
|
if (result.getResult() != ActionResult.PASS) {
|
||||||
info.setReturnValue(result);
|
info.setReturnValue(result);
|
||||||
}
|
}
|
||||||
|
@ -29,6 +28,6 @@ abstract class MixinItemStack {
|
||||||
@Inject(method = "finishUsing", at = @At("HEAD"))
|
@Inject(method = "finishUsing", at = @At("HEAD"))
|
||||||
private void onFinishUsing(World world, LivingEntity user, CallbackInfoReturnable<ItemStack> info) {
|
private void onFinishUsing(World world, LivingEntity user, CallbackInfoReturnable<ItemStack> info) {
|
||||||
ItemStack self = (ItemStack)(Object)this;
|
ItemStack self = (ItemStack)(Object)this;
|
||||||
((ToxicHolder)self.getItem()).getToxic(self, user).finishUsing(self, world, user);
|
((DietView.Holder)self.getItem()).getDiets(self).finishUsing(self, world, user);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,26 +0,0 @@
|
||||||
package com.minelittlepony.unicopia.mixin.client;
|
|
||||||
|
|
||||||
import java.util.List;
|
|
||||||
import org.jetbrains.annotations.Nullable;
|
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.item.toxin.ToxicHolder;
|
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
|
||||||
import net.minecraft.client.item.TooltipContext;
|
|
||||||
import net.minecraft.item.Item;
|
|
||||||
import net.minecraft.item.ItemStack;
|
|
||||||
import net.minecraft.text.Text;
|
|
||||||
import net.minecraft.world.World;
|
|
||||||
|
|
||||||
@Mixin(Item.class)
|
|
||||||
abstract class MixinItem implements ToxicHolder {
|
|
||||||
@Inject(method = "appendTooltip", at = @At("RETURN"))
|
|
||||||
private void onAppendTooltip(ItemStack stack, @Nullable World world, List<Text> tooltip, TooltipContext context, CallbackInfo into) {
|
|
||||||
getToxic(stack, MinecraftClient.getInstance().player).appendTooltip(MinecraftClient.getInstance().player, tooltip, context);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
package com.minelittlepony.unicopia.mixin.client;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
|
import com.minelittlepony.unicopia.diet.DietView;
|
||||||
|
import net.minecraft.client.item.TooltipContext;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.text.Text;
|
||||||
|
|
||||||
|
@Mixin(ItemStack.class)
|
||||||
|
abstract class MixinItemStack {
|
||||||
|
@Inject(method = "getTooltip", at = @At("RETURN"))
|
||||||
|
private void onGetTooltip(@Nullable PlayerEntity player, TooltipContext context, CallbackInfoReturnable<List<Text>> info) {
|
||||||
|
ItemStack self = (ItemStack)(Object)this;
|
||||||
|
((DietView.Holder)self.getItem()).getDiets(self).appendTooltip(self, player, info.getReturnValue(), context);
|
||||||
|
}
|
||||||
|
}
|
|
@ -24,7 +24,7 @@ public record MsgServerResources (
|
||||||
SpellTraits.all(),
|
SpellTraits.all(),
|
||||||
SpellbookChapterLoader.INSTANCE.getChapters(),
|
SpellbookChapterLoader.INSTANCE.getChapters(),
|
||||||
TreeTypeLoader.INSTANCE.getEntries(),
|
TreeTypeLoader.INSTANCE.getEntries(),
|
||||||
PonyDiets.getinstance()
|
PonyDiets.getInstance()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -469,12 +469,58 @@
|
||||||
"trait.unicopia.poison.name": "Poison",
|
"trait.unicopia.poison.name": "Poison",
|
||||||
"trait.unicopia.poison.description": "A deadly dart kill a beast.",
|
"trait.unicopia.poison.description": "A deadly dart kill a beast.",
|
||||||
|
|
||||||
|
"unicopia.diet.information": "Diet Information:",
|
||||||
|
"unicopia.diet.side_effects": "Side-Effects:",
|
||||||
|
"unicopia.diet.not_edible": "Item is not edible",
|
||||||
|
"unicopia.diet.base_multiplier": "Base Multiplier: %s%%",
|
||||||
|
"unicopia.diet.hunger.detailed": "Hunger gained: %s of %s (%s%%)",
|
||||||
|
"unicopia.diet.saturation.detailed": "Saturation gained: %s (%s%%)",
|
||||||
|
"unicopia.diet.hunger": "Hunger Ratio: %s%%",
|
||||||
|
"unicopia.diet.saturation": "Saturation Ratio: %s%%",
|
||||||
|
|
||||||
|
"tag.unicopia.food_types.rotten_meat": "Rotting Meat",
|
||||||
|
"tag.unicopia.food_types.raw_meat": "Fresh Meat",
|
||||||
|
"tag.unicopia.food_types.cooked_meat": "Prepared Meat",
|
||||||
|
"tag.unicopia.food_types.raw_fish": "Fresh Fish",
|
||||||
|
"tag.unicopia.food_types.cooked_fish": "Prepared Fish",
|
||||||
|
"tag.unicopia.food_types.raw_insect": "Bugs & Insects",
|
||||||
|
"tag.unicopia.food_types.cooked_insect": "Cooked Bugs & Insects",
|
||||||
|
"tag.unicopia.food_types.love": "Love",
|
||||||
|
"tag.unicopia.food_types.rocks": "Rocks",
|
||||||
|
"tag.unicopia.food_types.pinecone": "Nuts & Seeds",
|
||||||
|
"tag.unicopia.food_types.bat_ponys_delight": "Bat Pony Treats",
|
||||||
|
"tag.unicopia.food_types.cooked_sea_vegitables": "Prepared Fish Food",
|
||||||
|
"tag.unicopia.food_types.raw_sea_vegitables": "Fresh Fish Food",
|
||||||
|
"tag.unicopia.food_types.shells": "Sea Shells",
|
||||||
|
"tag.unicopia.food_types.shelly": "Sea Shells",
|
||||||
|
"tag.unicopia.food_types.candy": "Candy",
|
||||||
|
"tag.unicopia.food_types.desserts": "Desserts",
|
||||||
|
"tag.unicopia.food_types.fruits_and_vegetables": "Fruits & Vegetables",
|
||||||
|
"tag.unicopia.food_types.drinks": "Drinks",
|
||||||
|
|
||||||
|
"tag.unicopia.food_types.forage_edible_filling": "Bulky Plant Matter",
|
||||||
|
"tag.unicopia.food_types.forage_edible": "Plant Matter",
|
||||||
|
"tag.unicopia.food_types.forage_nauseating": "Nauseating",
|
||||||
|
"tag.unicopia.food_types.forage_prickly": "Prickly",
|
||||||
|
"tag.unicopia.food_types.forage_risky": "Unsafe",
|
||||||
|
"tag.unicopia.food_types.forage_strengthening": "Strength Enhancing",
|
||||||
|
"tag.unicopia.food_types.forage_severely_prickly": "Very Prickly",
|
||||||
|
"tag.unicopia.food_types.forage_severely_nauseating": "Sickening",
|
||||||
|
"tag.unicopia.food_types.forage_radioactive": "Glowy",
|
||||||
|
"tag.unicopia.food_types.forage_dangerous": "Dangerous",
|
||||||
|
"tag.unicopia.food_types.forage_blinding": "Toxic",
|
||||||
|
|
||||||
"toxicity.safe.name": "Safe",
|
"toxicity.safe.name": "Safe",
|
||||||
"toxicity.mild.name": "Mildly Toxic",
|
"toxicity.mild.name": "Mildly Toxic",
|
||||||
"toxicity.fair.name": "Fairly Toxic",
|
"toxicity.fair.name": "Fairly Toxic",
|
||||||
"toxicity.severe.name": "Toxic",
|
"toxicity.severe.name": "Toxic",
|
||||||
"toxicity.lethal.name": "Lethal",
|
"toxicity.lethal.name": "Lethal",
|
||||||
|
|
||||||
|
"affliction.unicopia.empty": "No Effect",
|
||||||
|
"affliction.unicopia.healing": "Gain %s%% health",
|
||||||
|
"affliction.unicopia.cure_love_sickness": "Cure Love Sickness",
|
||||||
|
"affliction.unicopia.lose_hunger": "Lose %s%% hunger",
|
||||||
|
|
||||||
"ability.unicopia.shoot": "Shoot Magic",
|
"ability.unicopia.shoot": "Shoot Magic",
|
||||||
"ability.unicopia.shoot.with_spell": "Shoot %s",
|
"ability.unicopia.shoot.with_spell": "Shoot %s",
|
||||||
"ability.unicopia.shoot.with_spell.active": "Shooting %s",
|
"ability.unicopia.shoot.with_spell.active": "Shooting %s",
|
||||||
|
@ -1068,7 +1114,7 @@
|
||||||
"advancements.unicopia.apple_route.description": "Start your journey towards the apple of legend",
|
"advancements.unicopia.apple_route.description": "Start your journey towards the apple of legend",
|
||||||
"advancements.unicopia.juice.title": "Refreshing",
|
"advancements.unicopia.juice.title": "Refreshing",
|
||||||
"advancements.unicopia.juice.description": "Finally a use for all these apples",
|
"advancements.unicopia.juice.description": "Finally a use for all these apples",
|
||||||
"advancements.unicopia.toast.title": "He Crispy and delicious!",
|
"advancements.unicopia.toast.title": "He's Crispy and delicious!",
|
||||||
"advancements.unicopia.toast.description": "Make a toasted companion",
|
"advancements.unicopia.toast.description": "Make a toasted companion",
|
||||||
"advancements.unicopia.burn_toast.title": "Toasty NOOOOOOO!",
|
"advancements.unicopia.burn_toast.title": "Toasty NOOOOOOO!",
|
||||||
"advancements.unicopia.burn_toast.description": "Burn Toasty",
|
"advancements.unicopia.burn_toast.description": "Burn Toasty",
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/cooked_fish",
|
"tags": [ "unicopia:food_types/cooked_fish" ],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 1,
|
||||||
|
"saturation": 0.1
|
||||||
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "fair",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/raw_fish",
|
"tags": [ "unicopia:food_types/raw_fish" ],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 1,
|
||||||
|
"saturation": 0.1
|
||||||
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "risky",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:poison",
|
"effect": "minecraft:poison",
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/rotten_fish",
|
"tags": [ "unicopia:food_types/rotten_fish" ],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 1,
|
||||||
|
"saturation": 0.1
|
||||||
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "severe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:poison",
|
"effect": "minecraft:poison",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_blinding",
|
"tags": [ "unicopia:food_types/forage_blinding" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "severe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:blindness",
|
"effect": "minecraft:blindness",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_dangerous",
|
"tags": [ "unicopia:food_types/forage_dangerous" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "mild",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_edible",
|
"tags": [ "unicopia:food_types/forage_edible" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": []
|
"effects": []
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_edible_filling",
|
"tags": [ "unicopia:food_types/forage_edible_filling" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 18,
|
"hunger": 18,
|
||||||
"saturation": 9
|
"saturation": 9
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": []
|
"effects": []
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_moderate",
|
"tags": [ "unicopia:food_types/forage_moderate" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "mild",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_nauseating",
|
"tags": [ "unicopia:food_types/forage_nauseating" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "severe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:weakness",
|
"effect": "minecraft:weakness",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_prickly",
|
"tags": [ "unicopia:food_types/forage_prickly" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:instant_damage",
|
"effect": "minecraft:instant_damage",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_radioactive",
|
"tags": [ "unicopia:food_types/forage_radioactive" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "severe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:glowing",
|
"effect": "minecraft:glowing",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_risky",
|
"tags": [ "unicopia:food_types/forage_risky" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "fair",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_severely_nauseating",
|
"tags": [ "unicopia:food_types/forage_severely_nauseating" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "severe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:weakness",
|
"effect": "minecraft:weakness",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_severely_prickly",
|
"tags": [ "unicopia:food_types/forage_severely_prickly" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "severe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:instant_damage",
|
"effect": "minecraft:instant_damage",
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/forage_strengthening",
|
"tags": [ "unicopia:food_types/forage_strengthening" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:strength",
|
"effect": "minecraft:strength",
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/cooked_insect",
|
"tags": [ "unicopia:food_types/cooked_insect" ],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 1,
|
||||||
|
"saturation": 0.1
|
||||||
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "severe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/raw_insect",
|
"tags": [ "unicopia:food_types/raw_insect" ],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 1,
|
||||||
|
"saturation": 0.1
|
||||||
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "lethal",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/cooked_meat",
|
"tags": [ "unicopia:food_types/cooked_meat" ],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 12,
|
||||||
|
"saturation": 1.2
|
||||||
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "fair",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/raw_meat",
|
"tags": [ "unicopia:food_types/raw_meat" ],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 1,
|
||||||
|
"saturation": 1
|
||||||
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "risky",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:poison",
|
"effect": "minecraft:poison",
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/rotten_meat",
|
"tags": [ "unicopia:food_types/rotten_meat" ],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 1,
|
||||||
|
"saturation": 1
|
||||||
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "severe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:poison",
|
"effect": "minecraft:poison",
|
||||||
|
|
|
@ -1,7 +1,10 @@
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/pinecone",
|
"tags": [ "unicopia:food_types/pinecone" ],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 1,
|
||||||
|
"saturation": 0.1
|
||||||
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"type": "unicopia:healing",
|
"type": "unicopia:healing",
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"tags": [ "unicopia:food_types/rocks" ],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 1,
|
||||||
|
"saturation": 0.1
|
||||||
|
},
|
||||||
|
"ailment": {
|
||||||
|
"effects": []
|
||||||
|
}
|
||||||
|
}
|
|
@ -3,16 +3,12 @@
|
||||||
"foraging_multiplier": 1,
|
"foraging_multiplier": 1,
|
||||||
"multipliers": [
|
"multipliers": [
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/cooked_fish" ],
|
||||||
"unicopia:food_types/cooked_fish"
|
|
||||||
],
|
|
||||||
"hunger": 1.5,
|
"hunger": 1.5,
|
||||||
"saturation": 1.5
|
"saturation": 1.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/raw_fish" ],
|
||||||
"unicopia:food_types/raw_fish"
|
|
||||||
],
|
|
||||||
"hunger": 0.5,
|
"hunger": 0.5,
|
||||||
"saturation": 0.6
|
"saturation": 0.6
|
||||||
},
|
},
|
||||||
|
@ -35,29 +31,25 @@
|
||||||
"saturation": 0
|
"saturation": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/pinecone" ],
|
||||||
"unicopia:food_types/pinecone"
|
|
||||||
],
|
|
||||||
"hunger": 0.9,
|
"hunger": 0.9,
|
||||||
"saturation": 0.9
|
"saturation": 0.9
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/cooked_fish",
|
"tags": [ "unicopia:food_types/cooked_fish" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/raw_fish",
|
"tags": [ "unicopia:food_types/raw_fish" ],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,74 +3,55 @@
|
||||||
"foraging_multiplier": 0.9,
|
"foraging_multiplier": 0.9,
|
||||||
"multipliers": [
|
"multipliers": [
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/cooked_fish" ],
|
||||||
"unicopia:food_types/cooked_fish"
|
|
||||||
],
|
|
||||||
"hunger": 0.75,
|
"hunger": 0.75,
|
||||||
"saturation": 0.75
|
"saturation": 0.75
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/raw_fish" ],
|
||||||
"unicopia:food_types/raw_fish"
|
|
||||||
],
|
|
||||||
"hunger": 0.5,
|
"hunger": 0.5,
|
||||||
"saturation": 0.6
|
"saturation": 0.6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/cooked_insect" ],
|
||||||
"unicopia:food_types/cooked_insect"
|
|
||||||
],
|
|
||||||
"hunger": 1.75,
|
"hunger": 1.75,
|
||||||
"saturation": 1.75
|
"saturation": 1.75
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/cooked_meat" ],
|
||||||
"unicopia:food_types/cooked_meat"
|
|
||||||
],
|
|
||||||
"hunger": 1.15,
|
"hunger": 1.15,
|
||||||
"saturation": 1.15
|
"saturation": 1.15
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/raw_insect" ],
|
||||||
"unicopia:food_types/raw_insect"
|
|
||||||
],
|
|
||||||
"hunger": 1,
|
"hunger": 1,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/raw_meat" ],
|
||||||
"unicopia:food_types/raw_meat"
|
|
||||||
],
|
|
||||||
"hunger": 0.25,
|
"hunger": 0.25,
|
||||||
"saturation": 0.25
|
"saturation": 0.25
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/rotten_meat" ],
|
||||||
"unicopia:food_types/rotten_meat"
|
|
||||||
],
|
|
||||||
"hunger": 0.2,
|
"hunger": 0.2,
|
||||||
"saturation": 0.2
|
"saturation": 0.2
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/love" ],
|
||||||
"unicopia:food_types/love"
|
|
||||||
],
|
|
||||||
"hunger": 0,
|
"hunger": 0,
|
||||||
"saturation": 0
|
"saturation": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/pinecone" ],
|
||||||
"unicopia:food_types/pinecone"
|
|
||||||
],
|
|
||||||
"hunger": 0.9,
|
"hunger": 0.9,
|
||||||
"saturation": 0.9
|
"saturation": 0.9
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/rotten_fish",
|
"tags": [ "unicopia:food_types/rotten_fish" ],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "mild",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
@ -87,14 +68,12 @@
|
||||||
"unicopia:food_types/cooked_meat"
|
"unicopia:food_types/cooked_meat"
|
||||||
],
|
],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/raw_insect",
|
"tags": [ "unicopia:food_types/raw_insect" ],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "mild",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
@ -110,7 +89,6 @@
|
||||||
"unicopia:food_types/rotten_meat"
|
"unicopia:food_types/rotten_meat"
|
||||||
],
|
],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "risky",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
@ -122,9 +100,8 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/bat_ponys_delight",
|
"tags": [ "unicopia:food_types/bat_ponys_delight" ],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "minecraft:health_boost",
|
"effect": "minecraft:health_boost",
|
||||||
|
|
|
@ -3,50 +3,37 @@
|
||||||
"foraging_multiplier": 0,
|
"foraging_multiplier": 0,
|
||||||
"multipliers": [
|
"multipliers": [
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/cooked_insect" ],
|
||||||
"unicopia:food_types/cooked_insect"
|
|
||||||
],
|
|
||||||
"hunger": 0.3,
|
"hunger": 0.3,
|
||||||
"saturation": 0.3
|
"saturation": 0.3
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/cooked_meat" ],
|
||||||
"unicopia:food_types/cooked_meat"
|
|
||||||
],
|
|
||||||
"hunger": 0.1,
|
"hunger": 0.1,
|
||||||
"saturation": 0.1
|
"saturation": 0.1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/raw_insect" ],
|
||||||
"unicopia:food_types/raw_insect"
|
|
||||||
],
|
|
||||||
"hunger": 1,
|
"hunger": 1,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/raw_meat" ],
|
||||||
"unicopia:food_types/raw_meat"
|
|
||||||
],
|
|
||||||
"hunger": 0.25,
|
"hunger": 0.25,
|
||||||
"saturation": 0.25
|
"saturation": 0.25
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/rotten_meat" ],
|
||||||
"unicopia:food_types/rotten_meat"
|
|
||||||
],
|
|
||||||
"hunger": 0.6,
|
"hunger": 0.6,
|
||||||
"saturation": 0.6
|
"saturation": 0.6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/love" ],
|
||||||
"unicopia:food_types/love"
|
|
||||||
],
|
|
||||||
"hunger": 1,
|
"hunger": 1,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default_effects": {
|
"default_effects": {
|
||||||
"toxicity": "fair",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
@ -66,15 +53,12 @@
|
||||||
},
|
},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/love" ],
|
||||||
"unicopia:food_types/love"
|
|
||||||
],
|
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"name": "Love Consumption",
|
"name": "Love Consumption",
|
||||||
|
@ -89,7 +73,6 @@
|
||||||
"unicopia:food_types/raw_fish"
|
"unicopia:food_types/raw_fish"
|
||||||
],
|
],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "fair",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
@ -114,21 +97,19 @@
|
||||||
"unicopia:food_types/rotten_meat"
|
"unicopia:food_types/rotten_meat"
|
||||||
],
|
],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [
|
||||||
"unicopia:food_types/forage_edible",
|
"unicopia:food_types/forage_edible",
|
||||||
"unicopia:food_types/forage_edible_filling",
|
"unicopia:food_types/forage_edible_filling"
|
||||||
],
|
],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 18,
|
"hunger": 18,
|
||||||
"saturation": 9
|
"saturation": 9
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "fair",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
|
|
@ -1,11 +1,18 @@
|
||||||
{
|
{
|
||||||
"default_multiplier": 0.3,
|
"default_multiplier": 1,
|
||||||
"foraging_multiplier": 1,
|
"foraging_multiplier": 1,
|
||||||
"multipliers": [
|
"multipliers": [
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [
|
||||||
"unicopia:food_types/cooked_fish"
|
"unicopia:food_types/candy",
|
||||||
|
"unicopia:food_types/desserts",
|
||||||
|
"unicopia:food_types/rocks"
|
||||||
],
|
],
|
||||||
|
"hunger": 2.5,
|
||||||
|
"saturation": 1.7
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tags": [ "unicopia:food_types/cooked_fish" ],
|
||||||
"hunger": 0.2,
|
"hunger": 0.2,
|
||||||
"saturation": 0.2
|
"saturation": 0.2
|
||||||
},
|
},
|
||||||
|
@ -29,11 +36,39 @@
|
||||||
"saturation": 0
|
"saturation": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/pinecone" ],
|
||||||
"unicopia:food_types/pinecone"
|
|
||||||
],
|
|
||||||
"hunger": 1,
|
"hunger": 1,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
}
|
}
|
||||||
|
],
|
||||||
|
"effects": [
|
||||||
|
{
|
||||||
|
"tags": [
|
||||||
|
"unicopia:food_types/candy",
|
||||||
|
"unicopia:food_types/rocks"
|
||||||
|
],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 5,
|
||||||
|
"saturation": 12,
|
||||||
|
"fastFood": true
|
||||||
|
},
|
||||||
|
"ailment": {
|
||||||
|
"effects": [ ]
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"tags": [
|
||||||
|
"unicopia:food_types/desserts"
|
||||||
|
],
|
||||||
|
"food_component": {
|
||||||
|
"hunger": 12,
|
||||||
|
"saturation": 32,
|
||||||
|
"eatenQuickly": true,
|
||||||
|
"fastFood": true
|
||||||
|
},
|
||||||
|
"ailment": {
|
||||||
|
"effects": [ ]
|
||||||
|
}
|
||||||
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,9 +19,7 @@
|
||||||
"saturation": 0.6
|
"saturation": 0.6
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/rotten_meat" ],
|
||||||
"unicopia:food_types/rotten_meat"
|
|
||||||
],
|
|
||||||
"hunger": 0.3,
|
"hunger": 0.3,
|
||||||
"saturation": 0.3
|
"saturation": 0.3
|
||||||
},
|
},
|
||||||
|
@ -35,29 +33,25 @@
|
||||||
"saturation": 0
|
"saturation": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/pinecone" ],
|
||||||
"unicopia:food_types/pinecone"
|
|
||||||
],
|
|
||||||
"hunger": 1,
|
"hunger": 1,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/cooked_fish",
|
"tags": [ "unicopia:food_types/cooked_fish" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/raw_fish",
|
"tags": [ "unicopia:food_types/raw_fish" ],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -71,14 +65,12 @@
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/pinecone",
|
"tags": [ "unicopia:food_types/pinecone" ],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"type": "unicopia:healing",
|
"type": "unicopia:healing",
|
||||||
|
|
|
@ -14,7 +14,6 @@
|
||||||
"unicopia:food_types/pinecone"
|
"unicopia:food_types/pinecone"
|
||||||
],
|
],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,16 +3,12 @@
|
||||||
"foraging_multiplier": 0.9,
|
"foraging_multiplier": 0.9,
|
||||||
"multipliers": [
|
"multipliers": [
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/cooked_meat" ],
|
||||||
"unicopia:food_types/cooked_meat"
|
|
||||||
],
|
|
||||||
"hunger": 1.5,
|
"hunger": 1.5,
|
||||||
"saturation": 1.5
|
"saturation": 1.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/raw_meat" ],
|
||||||
"unicopia:food_types/raw_meat"
|
|
||||||
],
|
|
||||||
"hunger": 0.5,
|
"hunger": 0.5,
|
||||||
"saturation": 0.6
|
"saturation": 0.6
|
||||||
},
|
},
|
||||||
|
@ -35,9 +31,7 @@
|
||||||
"saturation": 0
|
"saturation": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/pinecone" ],
|
||||||
"unicopia:food_types/pinecone"
|
|
||||||
],
|
|
||||||
"hunger": 0.9,
|
"hunger": 0.9,
|
||||||
"saturation": 0.9
|
"saturation": 0.9
|
||||||
}
|
}
|
||||||
|
@ -60,7 +54,6 @@
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,18 +1,14 @@
|
||||||
{
|
{
|
||||||
"default_multiplier": 0,
|
"default_multiplier": 0.5,
|
||||||
"foraging_multiplier": 1,
|
"foraging_multiplier": 1,
|
||||||
"multipliers": [
|
"multipliers": [
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/cooked_fish" ],
|
||||||
"unicopia:food_types/cooked_fish"
|
|
||||||
],
|
|
||||||
"hunger": 1.5,
|
"hunger": 1.5,
|
||||||
"saturation": 1.5
|
"saturation": 1.5
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/raw_fish" ],
|
||||||
"unicopia:food_types/raw_fish"
|
|
||||||
],
|
|
||||||
"hunger": 0.5,
|
"hunger": 0.5,
|
||||||
"saturation": 0.6
|
"saturation": 0.6
|
||||||
},
|
},
|
||||||
|
@ -35,25 +31,21 @@
|
||||||
"saturation": 0
|
"saturation": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/pinecone" ],
|
||||||
"unicopia:food_types/pinecone"
|
|
||||||
],
|
|
||||||
"hunger": 0.9,
|
"hunger": 0.9,
|
||||||
"saturation": 0.9
|
"saturation": 0.9
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/cooked_fish",
|
"tags": [ "unicopia:food_types/cooked_fish" ],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/raw_fish",
|
"tags": [ "unicopia:food_types/raw_fish" ],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "mild",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
|
|
@ -3,9 +3,7 @@
|
||||||
"foraging_multiplier": 0.7,
|
"foraging_multiplier": 0.7,
|
||||||
"multipliers": [
|
"multipliers": [
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/raw_sea_vegitable" ],
|
||||||
"unicopia:food_types/raw_sea_vegitable"
|
|
||||||
],
|
|
||||||
"hunger": 1,
|
"hunger": 1,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
|
@ -19,7 +17,6 @@
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
"default_effects": {
|
"default_effects": {
|
||||||
"toxicity": "fair",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
@ -30,30 +27,27 @@
|
||||||
},
|
},
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/cooked_fish",
|
"tags": [ "unicopia:food_types/cooked_fish" ],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/raw_fish",
|
"tags": [ "unicopia:food_types/raw_fish" ],
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [
|
||||||
"unicopia:food_types/forage_edible",
|
"unicopia:food_types/forage_edible",
|
||||||
"unicopia:food_types/forage_edible_filling",
|
"unicopia:food_types/forage_edible_filling"
|
||||||
],
|
],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 18,
|
"hunger": 18,
|
||||||
"saturation": 9
|
"saturation": 9
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "fair",
|
|
||||||
"effects": [
|
"effects": [
|
||||||
{
|
{
|
||||||
"effect": "unicopia:food_poisoning",
|
"effect": "unicopia:food_poisoning",
|
||||||
|
@ -64,46 +58,42 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/raw_sea_vegitable",
|
"tags": [ "unicopia:food_types/raw_sea_vegitable" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 2,
|
"hunger": 2,
|
||||||
"saturation": 1
|
"saturation": 1
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/cooked_sea_vegitable",
|
"tags": [ "unicopia:food_types/cooked_sea_vegitable" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 6,
|
"hunger": 6,
|
||||||
"saturation": 2
|
"saturation": 2
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/shells",
|
"tags": [ "unicopia:food_types/shells" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 3,
|
"hunger": 3,
|
||||||
"saturation": 5
|
"saturation": 5
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tag": "unicopia:food_types/shelly",
|
"tags": [ "unicopia:food_types/shelly" ],
|
||||||
"food_component": {
|
"food_component": {
|
||||||
"hunger": 6,
|
"hunger": 6,
|
||||||
"saturation": 7
|
"saturation": 7
|
||||||
},
|
},
|
||||||
"ailment": {
|
"ailment": {
|
||||||
"toxicity": "safe",
|
|
||||||
"effects": [ ]
|
"effects": [ ]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,11 +23,10 @@
|
||||||
"saturation": 0
|
"saturation": 0
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"tags": [
|
"tags": [ "unicopia:food_types/pinecone" ],
|
||||||
"unicopia:food_types/pinecone"
|
|
||||||
],
|
|
||||||
"hunger": 0.9,
|
"hunger": 0.9,
|
||||||
"saturation": 0.9
|
"saturation": 0.9
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"effects": []
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,10 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"unicopia:rock_candy",
|
||||||
|
"unicopia:candied_apple",
|
||||||
|
"minecraft:sugar",
|
||||||
|
{ "id": "bakersdelight:sweet_berry_cheesecake_slice", "required": false },
|
||||||
|
{ "id": "bakersdelight:cake_slice", "required": false }
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"minecraft:cake",
|
||||||
|
"#unicopia:pies",
|
||||||
|
{ "id": "bakersdelight:sweet_berry_cheesecake", "required": false }
|
||||||
|
]
|
||||||
|
}
|
|
@ -0,0 +1,6 @@
|
||||||
|
{
|
||||||
|
"replace": false,
|
||||||
|
"values": [
|
||||||
|
"unicopia:rock_stew"
|
||||||
|
]
|
||||||
|
}
|
|
@ -69,8 +69,8 @@
|
||||||
"client.MixinHeldItemRenderer",
|
"client.MixinHeldItemRenderer",
|
||||||
"client.MixinInGameHud",
|
"client.MixinInGameHud",
|
||||||
"client.MixinInGameHud$HeartType",
|
"client.MixinInGameHud$HeartType",
|
||||||
"client.MixinItem",
|
|
||||||
"client.MixinItemModels",
|
"client.MixinItemModels",
|
||||||
|
"client.MixinItemStack",
|
||||||
"client.MixinKeyboardInput",
|
"client.MixinKeyboardInput",
|
||||||
"client.MixinLivingEntityRenderer",
|
"client.MixinLivingEntityRenderer",
|
||||||
"client.MixinModelPart",
|
"client.MixinModelPart",
|
||||||
|
|
Loading…
Reference in a new issue