mirror of
https://github.com/Sollace/Unicopia.git
synced 2025-02-08 06:26:43 +01:00
wip
This commit is contained in:
parent
8a85f0709e
commit
16a7b96f81
27 changed files with 675 additions and 9 deletions
|
@ -22,6 +22,8 @@ import com.minelittlepony.unicopia.command.Commands;
|
|||
import com.minelittlepony.unicopia.compat.trinkets.TrinketsDelegate;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapterLoader;
|
||||
import com.minelittlepony.unicopia.container.UScreenHandlers;
|
||||
import com.minelittlepony.unicopia.diet.AfflictionType;
|
||||
import com.minelittlepony.unicopia.diet.DietsLoader;
|
||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||
import com.minelittlepony.unicopia.entity.effect.UPotions;
|
||||
import com.minelittlepony.unicopia.entity.mob.UEntities;
|
||||
|
@ -83,11 +85,7 @@ public class Unicopia implements ModInitializer {
|
|||
});
|
||||
NocturnalSleepManager.bootstrap();
|
||||
|
||||
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(TreeTypeLoader.INSTANCE);
|
||||
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(UEnchantments.POISONED_JOKE);
|
||||
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(new TraitLoader());
|
||||
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(StateMapLoader.INSTANCE);
|
||||
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(SpellbookChapterLoader.INSTANCE);
|
||||
registerServerDataReloaders(ResourceManagerHelper.get(ResourceType.SERVER_DATA));
|
||||
|
||||
UGameEvents.bootstrap();
|
||||
UBlocks.bootstrap();
|
||||
|
@ -98,6 +96,7 @@ public class Unicopia implements ModInitializer {
|
|||
USounds.bootstrap();
|
||||
Race.bootstrap();
|
||||
SpellType.bootstrap();
|
||||
AfflictionType.bootstrap();
|
||||
Abilities.bootstrap();
|
||||
UScreenHandlers.bootstrap();
|
||||
UWorldGen.bootstrap();
|
||||
|
@ -105,6 +104,15 @@ public class Unicopia implements ModInitializer {
|
|||
UDamageTypes.bootstrap();
|
||||
}
|
||||
|
||||
private void registerServerDataReloaders(ResourceManagerHelper registry) {
|
||||
registry.registerReloadListener(TreeTypeLoader.INSTANCE);
|
||||
registry.registerReloadListener(UEnchantments.POISONED_JOKE);
|
||||
registry.registerReloadListener(new TraitLoader());
|
||||
registry.registerReloadListener(StateMapLoader.INSTANCE);
|
||||
registry.registerReloadListener(SpellbookChapterLoader.INSTANCE);
|
||||
registry.registerReloadListener(new DietsLoader());
|
||||
}
|
||||
|
||||
public interface SidedAccess {
|
||||
Optional<Pony> getPony();
|
||||
|
||||
|
|
|
@ -0,0 +1,70 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.Codec;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.dynamic.Codecs;
|
||||
|
||||
public interface Affliction {
|
||||
Text NO_EFFECT_TEXT = Text.of("No Effect");
|
||||
Affliction EMPTY = new Affliction() {
|
||||
@Override
|
||||
public void afflict(PlayerEntity player, ItemStack stack) { }
|
||||
|
||||
@Override
|
||||
public Text getName() {
|
||||
return NO_EFFECT_TEXT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public AfflictionType<?> getType() {
|
||||
return AfflictionType.EMPTY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(PacketByteBuf buffer) { }
|
||||
};
|
||||
Codec<Affliction> CODEC = Codecs.xor(Codec.list(AfflictionType.CODEC)
|
||||
.mapResult(null)
|
||||
.xmap(
|
||||
afflictions -> {
|
||||
afflictions.removeIf(f -> f.getType() == AfflictionType.EMPTY);
|
||||
return switch (afflictions.size()) {
|
||||
case 0 -> EMPTY;
|
||||
case 1 -> afflictions.get(0);
|
||||
default -> new CompoundAffliction(afflictions);
|
||||
};
|
||||
},
|
||||
affliction -> ((CompoundAffliction)affliction).afflictions
|
||||
), AfflictionType.CODEC).xmap(
|
||||
either -> either.left().or(either::right).get(),
|
||||
affliction -> affliction instanceof CompoundAffliction ? Either.left(affliction) : Either.right(affliction)
|
||||
);
|
||||
|
||||
void afflict(PlayerEntity player, ItemStack stack);
|
||||
|
||||
default void appendTooltip(List<Text> tooltip) {
|
||||
tooltip.add(getName());
|
||||
}
|
||||
|
||||
Text getName();
|
||||
|
||||
AfflictionType<?> getType();
|
||||
|
||||
void toBuffer(PacketByteBuf buffer);
|
||||
|
||||
static void write(PacketByteBuf buffer, Affliction affliction) {
|
||||
buffer.writeIdentifier(affliction.getType().id());
|
||||
affliction.toBuffer(buffer);
|
||||
}
|
||||
|
||||
static Affliction read(PacketByteBuf buffer) {
|
||||
return AfflictionType.REGISTRY.get(buffer.readIdentifier()).reader().apply(buffer);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,44 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import com.google.gson.JsonObject;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.util.RegistryUtils;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
|
||||
import net.minecraft.network.PacketByteBuf.PacketReader;
|
||||
import net.minecraft.registry.Registry;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.dynamic.Codecs;
|
||||
|
||||
public record AfflictionType<T extends Affliction>(Codec<T> codec, Identifier id, PacketReader<T> reader) {
|
||||
public static final String DEFAULT_ID = "unicopia:apply_status_effect";
|
||||
public static final Registry<AfflictionType<?>> REGISTRY = RegistryUtils.createDefaulted(Unicopia.id("affliction_type"), DEFAULT_ID);
|
||||
@SuppressWarnings("unchecked")
|
||||
public static final Codec<Affliction> CODEC = Codecs.JSON_ELEMENT.<Affliction>flatXmap(json -> {
|
||||
JsonObject obj = json.getAsJsonObject();
|
||||
return Identifier.validate(obj.has("type") ? obj.get("type").getAsString() : AfflictionType.DEFAULT_ID).flatMap(type -> {
|
||||
return AfflictionType.REGISTRY.get(type).codec().parse(JsonOps.INSTANCE, json);
|
||||
});
|
||||
}, thing -> {
|
||||
AfflictionType<?> type = thing.getType();
|
||||
return ((Codec<Affliction>)type.codec()).encodeStart(JsonOps.INSTANCE, thing).map(json -> {
|
||||
if (json.isJsonObject()) {
|
||||
json.getAsJsonObject().addProperty("type", type.id().toString());
|
||||
}
|
||||
return json;
|
||||
});
|
||||
});
|
||||
|
||||
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<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<ClearLoveSicknessAffliction> CLEAR_LOVE_SICKNESS = register("clear_love_sickness", ClearLoveSicknessAffliction.CODEC, buffer -> ClearLoveSicknessAffliction.INSTANCE);
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
public static void bootstrap() { }
|
||||
}
|
23
src/main/java/com/minelittlepony/unicopia/diet/Ailment.java
Normal file
23
src/main/java/com/minelittlepony/unicopia/diet/Ailment.java
Normal file
|
@ -0,0 +1,23 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import com.minelittlepony.unicopia.item.toxin.Toxicity;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
public record Ailment(Toxicity toxicity, Affliction effects) {
|
||||
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)
|
||||
).apply(instance, Ailment::new));
|
||||
|
||||
public Ailment(PacketByteBuf buffer) {
|
||||
this(Toxicity.byName(buffer.readString()), Affliction.read(buffer));
|
||||
}
|
||||
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeString(toxicity.name());
|
||||
Affliction.write(buffer, effects);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,35 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import com.minelittlepony.unicopia.entity.effect.UEffects;
|
||||
import com.mojang.serialization.Codec;
|
||||
import net.minecraft.entity.effect.StatusEffects;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
public final class ClearLoveSicknessAffliction implements Affliction {
|
||||
public static final ClearLoveSicknessAffliction INSTANCE = new ClearLoveSicknessAffliction();
|
||||
public static final Codec<ClearLoveSicknessAffliction> CODEC = Codec.unit(INSTANCE);
|
||||
|
||||
@Override
|
||||
public AfflictionType<?> getType() {
|
||||
return AfflictionType.CLEAR_LOVE_SICKNESS;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afflict(PlayerEntity player, ItemStack stack) {
|
||||
player.heal(stack.isFood() ? stack.getItem().getFoodComponent().getHunger() : 1);
|
||||
player.removeStatusEffect(StatusEffects.NAUSEA);
|
||||
player.removeStatusEffect(UEffects.FOOD_POISONING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getName() {
|
||||
return Text.literal("Love");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
}
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.text.Text;
|
||||
|
||||
class CompoundAffliction implements Affliction {
|
||||
public final List<Affliction> afflictions;
|
||||
private final Text name;
|
||||
|
||||
public CompoundAffliction(List<Affliction> afflictions) {
|
||||
this.afflictions = afflictions;
|
||||
name = afflictions.stream().map(Affliction::getName).reduce(null, (a, b) -> {
|
||||
return a == null ? b : a.copy().append(" + ").append(b);
|
||||
});
|
||||
}
|
||||
|
||||
public CompoundAffliction(PacketByteBuf buffer) {
|
||||
this(buffer.readList(Affliction::read));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeCollection(afflictions, Affliction::write);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AfflictionType<?> getType() {
|
||||
return AfflictionType.MANY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void appendTooltip(List<Text> tooltip) {
|
||||
afflictions.forEach(i -> i.appendTooltip(tooltip));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void afflict(PlayerEntity player, ItemStack stack) {
|
||||
afflictions.forEach(i -> i.afflict(player, stack));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,82 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.registry.tag.TagKey;
|
||||
|
||||
public record DietProfile(
|
||||
float defaultMultiplier,
|
||||
float foragingMultiplier,
|
||||
List<Multiplier> multipliers,
|
||||
List<Effect> effects
|
||||
) {
|
||||
public static final Codec<DietProfile> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
Codec.FLOAT.fieldOf("default_multiplier").forGetter(DietProfile::defaultMultiplier),
|
||||
Codec.FLOAT.fieldOf("foraging_multiplier").forGetter(DietProfile::foragingMultiplier),
|
||||
Codec.list(Multiplier.CODEC).fieldOf("multipliers").forGetter(DietProfile::multipliers),
|
||||
Codec.list(Effect.CODEC).fieldOf("effects").forGetter(DietProfile::effects)
|
||||
).apply(instance, DietProfile::new));
|
||||
|
||||
public DietProfile(PacketByteBuf buffer) {
|
||||
this(buffer.readFloat(), buffer.readFloat(), buffer.readList(Multiplier::new), buffer.readList(Effect::new));
|
||||
}
|
||||
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeFloat(defaultMultiplier);
|
||||
buffer.writeFloat(foragingMultiplier);
|
||||
buffer.writeCollection(multipliers, (b, t) -> t.toBuffer(b));
|
||||
buffer.writeCollection(effects, (b, t) -> t.toBuffer(b));
|
||||
}
|
||||
|
||||
public Optional<Multiplier> findMultiplier(ItemStack stack) {
|
||||
return multipliers.stream().filter(m -> m.test(stack)).findFirst();
|
||||
}
|
||||
|
||||
public Optional<Effect> findEffect(ItemStack stack) {
|
||||
return effects.stream().filter(m -> m.test(stack)).findFirst();
|
||||
}
|
||||
|
||||
public record Multiplier(
|
||||
Set<TagKey<Item>> tags,
|
||||
float hunger,
|
||||
float saturation
|
||||
) implements Predicate<ItemStack> {
|
||||
public static final Codec<Set<TagKey<Item>>> TAGS_CODEC = Codec.list(TagKey.unprefixedCodec(RegistryKeys.ITEM)).xmap(
|
||||
l -> l.stream().distinct().collect(Collectors.toSet()),
|
||||
set -> new ArrayList<>(set)
|
||||
);
|
||||
public static final Codec<Multiplier> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
TAGS_CODEC.fieldOf("tags").forGetter(Multiplier::tags),
|
||||
Codec.FLOAT.fieldOf("hunger").forGetter(Multiplier::hunger),
|
||||
Codec.FLOAT.fieldOf("saturation").forGetter(Multiplier::saturation)
|
||||
).apply(instance, Multiplier::new));
|
||||
|
||||
public Multiplier(PacketByteBuf buffer) {
|
||||
this(buffer.readCollection(HashSet::new, p -> TagKey.of(RegistryKeys.ITEM, p.readIdentifier())), buffer.readFloat(), buffer.readFloat());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(ItemStack stack) {
|
||||
return tags.stream().anyMatch(tag -> stack.isIn(tag));
|
||||
}
|
||||
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeCollection(tags, (p, t) -> p.writeIdentifier(t.id()));
|
||||
buffer.writeFloat(hunger);
|
||||
buffer.writeFloat(saturation);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.Executor;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.Unicopia;
|
||||
import com.minelittlepony.unicopia.util.Resources;
|
||||
import com.mojang.logging.LogUtils;
|
||||
import com.mojang.serialization.JsonOps;
|
||||
|
||||
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
|
||||
import net.minecraft.resource.JsonDataLoader;
|
||||
import net.minecraft.resource.ResourceManager;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.profiler.Profiler;
|
||||
|
||||
public class DietsLoader implements IdentifiableResourceReloadListener {
|
||||
private static final Logger LOGGER = LogUtils.getLogger();
|
||||
private static final Identifier ID = Unicopia.id("diets");
|
||||
|
||||
@Override
|
||||
public Identifier getFabricId() {
|
||||
return ID;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> reload(Synchronizer sync, ResourceManager manager,
|
||||
Profiler prepareProfiler, Profiler applyProfiler,
|
||||
Executor prepareExecutor, Executor applyExecutor) {
|
||||
|
||||
var dietsLoadTask = loadData(manager, prepareExecutor, "diets/races").thenApplyAsync(data -> {
|
||||
Map<Race, DietProfile> profiles = new HashMap<>();
|
||||
for (var entry : data.entrySet()) {
|
||||
Identifier id = entry.getKey();
|
||||
Race.REGISTRY.getOrEmpty(id).ifPresentOrElse(race -> DietProfile.CODEC.parse(JsonOps.INSTANCE, entry.getValue())
|
||||
.resultOrPartial(LOGGER::error)
|
||||
.ifPresent(profile -> profiles.put(race, profile)), () -> LOGGER.warn("Skipped diet for unknown race: " + id));
|
||||
}
|
||||
return profiles;
|
||||
}, applyExecutor);
|
||||
|
||||
var effectsLoadTask = loadData(manager, prepareExecutor, "diets/food_effects").thenApplyAsync(data -> data.values().stream()
|
||||
.map(value -> Effect.CODEC.parse(JsonOps.INSTANCE, value)
|
||||
.resultOrPartial(LOGGER::error))
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.toList());
|
||||
|
||||
var future = CompletableFuture.allOf(dietsLoadTask, effectsLoadTask);
|
||||
sync.getClass();
|
||||
return future.thenRunAsync(() -> {
|
||||
PonyDiets.load(new PonyDiets(
|
||||
dietsLoadTask.getNow(Map.of()),
|
||||
effectsLoadTask.getNow(List.of())
|
||||
));
|
||||
}, applyExecutor);
|
||||
}
|
||||
|
||||
private static CompletableFuture<Map<Identifier, JsonElement>> loadData(ResourceManager manager, Executor prepareExecutor, String path) {
|
||||
return CompletableFuture.supplyAsync(() -> {
|
||||
Map<Identifier, JsonElement> results = new HashMap<>();
|
||||
JsonDataLoader.load(manager, path, Resources.GSON, results);
|
||||
return results;
|
||||
});
|
||||
}
|
||||
}
|
56
src/main/java/com/minelittlepony/unicopia/diet/Effect.java
Normal file
56
src/main/java/com/minelittlepony/unicopia/diet/Effect.java
Normal file
|
@ -0,0 +1,56 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.registry.RegistryKeys;
|
||||
import net.minecraft.registry.tag.TagKey;
|
||||
|
||||
public record Effect(
|
||||
TagKey<Item> tag,
|
||||
Optional<FoodComponent> foodComponent,
|
||||
Ailment ailment
|
||||
) implements Predicate<ItemStack> {
|
||||
public static final Codec<Effect> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
TagKey.unprefixedCodec(RegistryKeys.ITEM).fieldOf("tag").forGetter(Effect::tag),
|
||||
FoodComponent.CODEC.optionalFieldOf("food_component").forGetter(Effect::foodComponent),
|
||||
Ailment.CODEC.fieldOf("ailment").forGetter(Effect::ailment)
|
||||
).apply(instance, Effect::new));
|
||||
|
||||
public Effect(PacketByteBuf buffer) {
|
||||
this(TagKey.of(RegistryKeys.ITEM, buffer.readIdentifier()), buffer.readOptional(FoodComponent::new), new Ailment(buffer));
|
||||
}
|
||||
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeIdentifier(tag.id());
|
||||
buffer.writeOptional(foodComponent, (b, f) -> f.toBuffer(b));
|
||||
ailment.toBuffer(buffer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean test(ItemStack stack) {
|
||||
return stack.isIn(tag);
|
||||
}
|
||||
|
||||
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,43 @@
|
|||
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);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
import com.minelittlepony.unicopia.Race;
|
||||
import com.minelittlepony.unicopia.diet.DietProfile.Multiplier;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
|
||||
public class PonyDiets {
|
||||
private final Map<Race, DietProfile> diets;
|
||||
private final List<Effect> effects;
|
||||
|
||||
static PonyDiets INSTANCE = new PonyDiets(Map.of(), List.of());
|
||||
|
||||
public static PonyDiets getinstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static void load(PonyDiets diets) {
|
||||
INSTANCE = diets;
|
||||
}
|
||||
|
||||
PonyDiets(Map<Race, DietProfile> diets, List<Effect> effects) {
|
||||
this.diets = diets;
|
||||
this.effects = effects;
|
||||
}
|
||||
|
||||
public PonyDiets(PacketByteBuf buffer) {
|
||||
this(buffer.readMap(b -> b.readRegistryValue(Race.REGISTRY), DietProfile::new), buffer.readList(Effect::new));
|
||||
}
|
||||
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeMap(diets, (b, r) -> b.writeRegistryValue(Race.REGISTRY, r), (b, e) -> e.toBuffer(b));
|
||||
buffer.writeCollection(effects, (b, e) -> e.toBuffer(b));
|
||||
}
|
||||
|
||||
public Optional<DietProfile> getDiet(Race race) {
|
||||
return Optional.ofNullable(diets.get(race));
|
||||
}
|
||||
|
||||
public Optional<Effect> getEffects(ItemStack stack) {
|
||||
return effects.stream().filter(effect -> effect.test(stack)).findFirst();
|
||||
}
|
||||
|
||||
public Optional<Effect> getEffects(ItemStack stack, Pony pony) {
|
||||
return getDiet(pony.getObservedSpecies()).flatMap(diet -> diet.findEffect(stack)).or(() -> getEffects(stack));
|
||||
}
|
||||
|
||||
public Optional<Multiplier> getMultiplier(ItemStack stack, Pony pony) {
|
||||
return getDiet(pony.getObservedSpecies()).flatMap(diet -> diet.findMultiplier(stack));
|
||||
}
|
||||
}
|
39
src/main/java/com/minelittlepony/unicopia/diet/Range.java
Normal file
39
src/main/java/com/minelittlepony/unicopia/diet/Range.java
Normal file
|
@ -0,0 +1,39 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import com.mojang.datafixers.util.Either;
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.util.dynamic.Codecs;
|
||||
|
||||
public record Range(int min, int max) {
|
||||
public static final Codec<Range> CODEC = Codecs.xor(
|
||||
Codec.INT.xmap(value -> Range.of(value, -1), range -> range.min()),
|
||||
RecordCodecBuilder.create(instance -> instance.group(
|
||||
Codec.INT.fieldOf("min").forGetter(Range::min),
|
||||
Codec.INT.fieldOf("max").forGetter(Range::max)
|
||||
).apply(instance, Range::of))
|
||||
).xmap(either -> either.left().or(either::right).get(), l -> Either.right(l));
|
||||
|
||||
public static Range of(int min, int max) {
|
||||
return new Range(min, max);
|
||||
}
|
||||
|
||||
public static Range of(PacketByteBuf buffer) {
|
||||
return of(buffer.readInt(), buffer.readInt());
|
||||
}
|
||||
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeInt(min);
|
||||
buffer.writeInt(max);
|
||||
}
|
||||
|
||||
public int getTicks(int currentTicks) {
|
||||
return clamp((min * 20) + currentTicks);
|
||||
}
|
||||
|
||||
public int clamp(int value) {
|
||||
return max > 0 ? Math.min(value, max * 20) : value;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,78 @@
|
|||
package com.minelittlepony.unicopia.diet;
|
||||
|
||||
import com.mojang.serialization.Codec;
|
||||
import com.mojang.serialization.codecs.RecordCodecBuilder;
|
||||
|
||||
import net.minecraft.entity.attribute.EntityAttributes;
|
||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.PacketByteBuf;
|
||||
import net.minecraft.registry.Registries;
|
||||
import net.minecraft.text.MutableText;
|
||||
import net.minecraft.text.Text;
|
||||
import net.minecraft.util.Identifier;
|
||||
import net.minecraft.util.StringHelper;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
|
||||
public record StatusEffectAffliction(Identifier effect, Range seconds, Range amplifier, int chance) implements Affliction {
|
||||
public static final Codec<StatusEffectAffliction> CODEC = RecordCodecBuilder.create(instance -> instance.group(
|
||||
Identifier.CODEC.fieldOf("effect").forGetter(StatusEffectAffliction::effect),
|
||||
Range.CODEC.fieldOf("seconds").forGetter(StatusEffectAffliction::seconds),
|
||||
Range.CODEC.optionalFieldOf("amplifier", Range.of(0, -1)).forGetter(StatusEffectAffliction::amplifier),
|
||||
Codec.INT.optionalFieldOf("chance", 0).forGetter(StatusEffectAffliction::chance)
|
||||
).apply(instance, StatusEffectAffliction::new));
|
||||
|
||||
public StatusEffectAffliction(PacketByteBuf buffer) {
|
||||
this(buffer.readIdentifier(), Range.of(buffer), Range.of(buffer), buffer.readInt());
|
||||
}
|
||||
|
||||
public void toBuffer(PacketByteBuf buffer) {
|
||||
buffer.writeIdentifier(effect);
|
||||
seconds.toBuffer(buffer);
|
||||
amplifier.toBuffer(buffer);
|
||||
buffer.writeInt(chance);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AfflictionType<?> getType() {
|
||||
return AfflictionType.APPLY_STATUS_EFFECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afflict(PlayerEntity player, ItemStack stack) {
|
||||
if (chance > 0 && player.getWorld().random.nextInt(chance) > 0) {
|
||||
return;
|
||||
}
|
||||
Registries.STATUS_EFFECT.getOrEmpty(effect).ifPresent(effect -> {
|
||||
float health = player.getHealth();
|
||||
StatusEffectInstance current = player.getStatusEffect(effect);
|
||||
player.addStatusEffect(new StatusEffectInstance(effect,
|
||||
seconds.getTicks(current == null ? 0 : current.getDuration()),
|
||||
amplifier.getTicks(current == null ? 0 : current.getAmplifier())
|
||||
));
|
||||
// keep original health
|
||||
if (effect.getAttributeModifiers().containsKey(EntityAttributes.GENERIC_MAX_HEALTH)) {
|
||||
player.setHealth(MathHelper.clamp(health, 0, player.getMaxHealth()));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Text getName() {
|
||||
return Registries.STATUS_EFFECT.getOrEmpty(effect).map(effect -> {
|
||||
MutableText text = effect.getName().copy();
|
||||
|
||||
if (amplifier.min() > 0) {
|
||||
text = Text.translatable("potion.withAmplifier", text, Text.translatable("potion.potency." + (amplifier.min() * 20)));
|
||||
}
|
||||
|
||||
text = Text.translatable("potion.withDuration", text, StringHelper.formatTicks(seconds.min() * 20));
|
||||
|
||||
if (chance > 0) {
|
||||
text = Text.translatable("potion.withChance", chance, text);
|
||||
}
|
||||
return (Text)text;
|
||||
}).orElse(Text.of("No Effect"));
|
||||
}
|
||||
}
|
|
@ -94,7 +94,6 @@ public interface Toxin extends Affliction {
|
|||
};
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
static Toxin of(Text name, Affliction affliction) {
|
||||
return new Toxin() {
|
||||
@Override
|
||||
|
|
|
@ -6,6 +6,7 @@ import com.minelittlepony.unicopia.InteractionManager;
|
|||
import com.minelittlepony.unicopia.ability.data.tree.TreeTypeLoader;
|
||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
|
||||
import com.minelittlepony.unicopia.container.SpellbookChapterLoader;
|
||||
import com.minelittlepony.unicopia.diet.PonyDiets;
|
||||
import com.sollace.fabwork.api.packets.Packet;
|
||||
|
||||
import net.minecraft.entity.player.PlayerEntity;
|
||||
|
@ -15,13 +16,15 @@ import net.minecraft.util.Identifier;
|
|||
public record MsgServerResources (
|
||||
Map<Identifier, SpellTraits> traits,
|
||||
Map<Identifier, ?> chapters,
|
||||
Map<Identifier, TreeTypeLoader.TreeTypeDef> treeTypes
|
||||
Map<Identifier, TreeTypeLoader.TreeTypeDef> treeTypes,
|
||||
PonyDiets diets
|
||||
) implements Packet<PlayerEntity> {
|
||||
public MsgServerResources() {
|
||||
this(
|
||||
SpellTraits.all(),
|
||||
SpellbookChapterLoader.INSTANCE.getChapters(),
|
||||
TreeTypeLoader.INSTANCE.getEntries()
|
||||
TreeTypeLoader.INSTANCE.getEntries(),
|
||||
PonyDiets.getinstance()
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -29,7 +32,8 @@ public record MsgServerResources (
|
|||
this(
|
||||
buffer.readMap(PacketByteBuf::readIdentifier, SpellTraits::fromPacket),
|
||||
InteractionManager.instance().readChapters(buffer),
|
||||
buffer.readMap(PacketByteBuf::readIdentifier, TreeTypeLoader.TreeTypeDef::new)
|
||||
buffer.readMap(PacketByteBuf::readIdentifier, TreeTypeLoader.TreeTypeDef::new),
|
||||
new PonyDiets(buffer)
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -38,5 +42,6 @@ public record MsgServerResources (
|
|||
buffer.writeMap(traits, PacketByteBuf::writeIdentifier, (r, v) -> v.write(r));
|
||||
buffer.writeMap(chapters, PacketByteBuf::writeIdentifier, (r, v) -> ((SpellbookChapterLoader.Chapter)v).write(r));
|
||||
buffer.writeMap(treeTypes, PacketByteBuf::writeIdentifier, (r, v) -> v.write(r));
|
||||
diets.toBuffer(buffer);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,6 +15,7 @@ import com.minelittlepony.unicopia.client.UnicopiaClient;
|
|||
import com.minelittlepony.unicopia.client.gui.TribeSelectionScreen;
|
||||
import com.minelittlepony.unicopia.client.gui.spellbook.ClientChapters;
|
||||
import com.minelittlepony.unicopia.client.gui.spellbook.SpellbookChapterList.Chapter;
|
||||
import com.minelittlepony.unicopia.diet.PonyDiets;
|
||||
import com.minelittlepony.unicopia.entity.mob.UEntities;
|
||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||
import com.minelittlepony.unicopia.network.*;
|
||||
|
@ -97,6 +98,7 @@ public class ClientNetworkHandlerImpl {
|
|||
SpellTraits.load(packet.traits());
|
||||
ClientChapters.load((Map<Identifier, Chapter>)packet.chapters());
|
||||
TreeTypes.load(packet.treeTypes());
|
||||
PonyDiets.load(packet.diets());
|
||||
}
|
||||
|
||||
private void handlePlayerAnimation(PlayerEntity sender, MsgPlayerAnimationChange packet) {
|
||||
|
|
|
@ -374,6 +374,7 @@
|
|||
"item.minecraft.lingering_potion.effect.unicopia.tribe_swap_hippogriff": "Lingering Potion of Hippogriff Metamorphosis",
|
||||
"item.minecraft.tipped_arrow.effect.unicopia.tribe_swap_hippogriff": "Arrow of Hippogriff Metamorphosis",
|
||||
|
||||
"potion.withChance": "1 in %s chance of %s",
|
||||
"potion.potency.6": "VII",
|
||||
|
||||
"spell.unicopia.frost": "Frost",
|
||||
|
|
Loading…
Reference in a new issue