1.20.2 -> 1.20.4

This commit is contained in:
Sollace 2023-12-30 11:55:26 +01:00
parent e361e7e83d
commit d461b9ae04
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
60 changed files with 601 additions and 272 deletions

View file

@ -3,10 +3,10 @@ org.gradle.daemon=false
# Fabric Properties # Fabric Properties
# check these on https://fabricmc.net/develop # check these on https://fabricmc.net/develop
minecraft_version=1.20.2-rc1 minecraft_version=1.20.4
yarn_mappings=1.20.2-rc1+build.2 yarn_mappings=1.20.4+build.1
loader_version=0.14.22 loader_version=0.15.1
fabric_version=0.88.5+1.20.2 fabric_version=0.91.2+1.20.4
# Mod Properties # Mod Properties
group=com.minelittlepony group=com.minelittlepony
@ -15,15 +15,15 @@ org.gradle.daemon=false
description=Magical Abilities for Mine Little Pony! description=Magical Abilities for Mine Little Pony!
# Publishing # Publishing
minecraft_version_range=>=1.20.2 minecraft_version_range=>=1.20.3
modrinth_loader_type=fabric modrinth_loader_type=fabric
modrinth_project_id=9K7RJlvM modrinth_project_id=9K7RJlvM
# Dependencies # Dependencies
fabwork_version=1.3.0+1.20.2 fabwork_version=1.3.0+1.20.2
modmenu_version=8.0.0-beta.1 modmenu_version=9.0.0-pre.1
minelp_version=4.11.1+1.20.2 minelp_version=4.11.5+1.20.2
kirin_version=1.16.0+1.20.2 kirin_version=1.17.0+1.20.4
reach_attributes_version=2.3.3 reach_attributes_version=2.3.3
trinkets_version=3.8.0 trinkets_version=3.8.0
terraformer_api_version=8.0.0-beta.1 terraformer_api_version=8.0.0-beta.1

View file

@ -18,7 +18,6 @@ import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
import net.minecraft.recipe.RecipeCodecs;
import net.minecraft.recipe.RecipeSerializer; import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.util.collection.DefaultedList; import net.minecraft.util.collection.DefaultedList;
@ -125,7 +124,7 @@ public class SpellCraftingRecipe implements SpellbookRecipe {
} }
public static class Serializer implements RecipeSerializer<SpellCraftingRecipe> { public static class Serializer implements RecipeSerializer<SpellCraftingRecipe> {
private static final Codec<ItemStack> RESULT_CODEC = CodecUtils.extend(RecipeCodecs.CRAFTING_RESULT, SpellType.REGISTRY.getCodec().fieldOf("spell")).xmap( private static final Codec<ItemStack> RESULT_CODEC = CodecUtils.extend(ItemStack.RECIPE_RESULT_CODEC, SpellType.REGISTRY.getCodec().fieldOf("spell")).xmap(
pair -> pair.getSecond().map(spell -> EnchantableItem.enchant(pair.getFirst().orElse(ItemStack.EMPTY), spell)).orElse(pair.getFirst().orElse(ItemStack.EMPTY)), pair -> pair.getSecond().map(spell -> EnchantableItem.enchant(pair.getFirst().orElse(ItemStack.EMPTY), spell)).orElse(pair.getFirst().orElse(ItemStack.EMPTY)),
stack -> Pair.of(Optional.of(stack), EnchantableItem.getSpellKeyOrEmpty(stack)) stack -> Pair.of(Optional.of(stack), EnchantableItem.getSpellKeyOrEmpty(stack))
); );

View file

@ -1,23 +1,29 @@
package com.minelittlepony.unicopia.ability.magic.spell.crafting; package com.minelittlepony.unicopia.ability.magic.spell.crafting;
import java.util.function.Function;
import com.minelittlepony.unicopia.item.EnchantableItem; import com.minelittlepony.unicopia.item.EnchantableItem;
import com.minelittlepony.unicopia.item.URecipes; import com.minelittlepony.unicopia.item.URecipes;
import com.minelittlepony.unicopia.util.InventoryUtil; import com.minelittlepony.unicopia.util.InventoryUtil;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.inventory.RecipeInputInventory; import net.minecraft.inventory.RecipeInputInventory;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.network.PacketByteBuf; import net.minecraft.network.PacketByteBuf;
import net.minecraft.recipe.RawShapedRecipe;
import net.minecraft.recipe.RecipeSerializer; import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.ShapedRecipe; import net.minecraft.recipe.ShapedRecipe;
import net.minecraft.recipe.book.CraftingRecipeCategory;
import net.minecraft.registry.DynamicRegistryManager; import net.minecraft.registry.DynamicRegistryManager;
import net.minecraft.util.dynamic.Codecs;
public class SpellShapedCraftingRecipe extends ShapedRecipe { public class SpellShapedCraftingRecipe extends ShapedRecipe {
private final RawShapedRecipe raw;
private final ItemStack result;
public SpellShapedCraftingRecipe(ShapedRecipe recipe) { public SpellShapedCraftingRecipe(String group, CraftingRecipeCategory category, RawShapedRecipe raw, ItemStack result, boolean showNotification) {
super(recipe.getGroup(), recipe.getCategory(), recipe.getWidth(), recipe.getHeight(), recipe.getIngredients(), recipe.getResult(null)); super(group, category, raw, result, showNotification);
this.raw = raw;
this.result = result;
} }
@Override @Override
@ -36,15 +42,37 @@ public class SpellShapedCraftingRecipe extends ShapedRecipe {
return URecipes.CRAFTING_MAGICAL_SERIALIZER; return URecipes.CRAFTING_MAGICAL_SERIALIZER;
} }
public static class Serializer extends ShapedRecipe.Serializer { public static class Serializer implements RecipeSerializer<SpellShapedCraftingRecipe> {
public static final Codec<SpellShapedCraftingRecipe> CODEC = RecordCodecBuilder.create(instance -> instance.group(
Codecs.createStrictOptionalFieldCodec(Codec.STRING, "group", "").forGetter(SpellShapedCraftingRecipe::getGroup),
CraftingRecipeCategory.CODEC.fieldOf("category").orElse(CraftingRecipeCategory.MISC).forGetter(SpellShapedCraftingRecipe::getCategory),
RawShapedRecipe.CODEC.forGetter(recipe -> recipe.raw), ItemStack.RECIPE_RESULT_CODEC.fieldOf("result").forGetter(recipe -> recipe.result),
Codecs.createStrictOptionalFieldCodec(Codec.BOOL, "show_notification", true).forGetter(SpellShapedCraftingRecipe::showNotification)
).apply(instance, SpellShapedCraftingRecipe::new));
@Override @Override
public Codec<ShapedRecipe> codec() { public Codec<SpellShapedCraftingRecipe> codec() {
return super.codec().xmap(SpellShapedCraftingRecipe::new, Function.identity()); return CODEC;
} }
@Override @Override
public ShapedRecipe read(PacketByteBuf buffer) { public SpellShapedCraftingRecipe read(PacketByteBuf buffer) {
return new SpellShapedCraftingRecipe(super.read(buffer)); return new SpellShapedCraftingRecipe(
buffer.readString(),
buffer.readEnumConstant(CraftingRecipeCategory.class),
RawShapedRecipe.readFromBuf(buffer),
buffer.readItemStack(),
buffer.readBoolean()
);
}
@Override
public void write(PacketByteBuf packetByteBuf, SpellShapedCraftingRecipe shapedRecipe) {
packetByteBuf.writeString(shapedRecipe.getGroup());
packetByteBuf.writeEnumConstant(shapedRecipe.getCategory());
shapedRecipe.raw.writeToBuf(packetByteBuf);
packetByteBuf.writeItemStack(shapedRecipe.result);
packetByteBuf.writeBoolean(shapedRecipe.showNotification());
} }
} }
} }

View file

@ -4,27 +4,23 @@ import java.util.Optional;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.util.CodecUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.fabricmc.fabric.api.util.TriState;
import net.minecraft.advancement.criterion.AbstractCriterion; import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer; import net.minecraft.predicate.entity.EntityPredicate;
import net.minecraft.predicate.entity.LootContextPredicate; import net.minecraft.predicate.entity.LootContextPredicate;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.JsonHelper; import net.minecraft.util.dynamic.Codecs;
public class CustomEventCriterion extends AbstractCriterion<CustomEventCriterion.Conditions> { public class CustomEventCriterion extends AbstractCriterion<CustomEventCriterion.Conditions> {
@Override @Override
protected Conditions conditionsFromJson(JsonObject json, Optional<LootContextPredicate> playerPredicate, AdvancementEntityPredicateDeserializer deserializer) { public Codec<Conditions> getConditionsCodec() {
return new Conditions( return Conditions.CODEC;
playerPredicate,
JsonHelper.getString(json, "event"),
RacePredicate.fromJson(json.get("race")),
json.has("flying") ? json.get("flying").getAsBoolean() : null,
JsonHelper.getInt(json, "repeats", 0)
);
} }
public CustomEventCriterion.Trigger createTrigger(String name) { public CustomEventCriterion.Trigger createTrigger(String name) {
@ -41,42 +37,26 @@ public class CustomEventCriterion extends AbstractCriterion<CustomEventCriterion
void trigger(@Nullable Entity player); void trigger(@Nullable Entity player);
} }
public static class Conditions extends AbstractCriterionConditions { public record Conditions (
private final String event; Optional<LootContextPredicate> player,
String event,
private final RacePredicate races; RacePredicate races,
TriState flying,
private final Boolean flying; int repeatCount) implements AbstractCriterion.Conditions {
public static final Codec<Conditions> CODEC = RecordCodecBuilder.create(instance -> instance.group(
private final int repeatCount; Codecs.createStrictOptionalFieldCodec(EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC, "player").forGetter(Conditions::player),
Codec.STRING.fieldOf("event").forGetter(Conditions::event),
public Conditions(Optional<LootContextPredicate> playerPredicate, String event, RacePredicate races, Boolean flying, int repeatCount) { RacePredicate.CODEC.fieldOf("races").forGetter(Conditions::races),
super(playerPredicate); CodecUtils.tristateOf("flying").forGetter(Conditions::flying),
this.event = event; Codec.INT.optionalFieldOf("repeatCount", 0).forGetter(Conditions::repeatCount)
this.races = races; ).apply(instance, Conditions::new));
this.flying = flying;
this.repeatCount = repeatCount;
}
public boolean test(String event, int count, ServerPlayerEntity player) { public boolean test(String event, int count, ServerPlayerEntity player) {
boolean isFlying = Pony.of(player).getPhysics().isFlying();
return this.event.equalsIgnoreCase(event) return this.event.equalsIgnoreCase(event)
&& races.test(player) && races.test(player)
&& (flying == null || flying == Pony.of(player).getPhysics().isFlying()) && flying.orElse(isFlying) == isFlying
&& (repeatCount <= 0 || (count > 0 && count % repeatCount == 0)); && (repeatCount <= 0 || (count > 0 && count % repeatCount == 0));
} }
@Override
public JsonObject toJson() {
JsonObject json = super.toJson();
json.addProperty("event", event);
json.add("race", races.toJson());
if (flying != null) {
json.addProperty("flying", flying);
}
if (repeatCount > 0) {
json.addProperty("repeats", repeatCount);
}
return json;
}
} }
} }

View file

@ -2,23 +2,22 @@ package com.minelittlepony.unicopia.advancement;
import java.util.Optional; import java.util.Optional;
import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.advancement.criterion.AbstractCriterion; import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer; import net.minecraft.predicate.entity.EntityPredicate;
import net.minecraft.predicate.entity.LootContextPredicate; import net.minecraft.predicate.entity.LootContextPredicate;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.JsonHelper; import net.minecraft.util.dynamic.Codecs;
public class RaceChangeCriterion extends AbstractCriterion<RaceChangeCriterion.Conditions> { public class RaceChangeCriterion extends AbstractCriterion<RaceChangeCriterion.Conditions> {
@Override @Override
protected Conditions conditionsFromJson(JsonObject json, Optional<LootContextPredicate> playerPredicate, AdvancementEntityPredicateDeserializer deserializer) { public Codec<Conditions> getConditionsCodec() {
return new Conditions(playerPredicate, Race.fromName(JsonHelper.getString(json, "race"), Race.EARTH)); return Conditions.CODEC;
} }
public void trigger(PlayerEntity player) { public void trigger(PlayerEntity player) {
@ -27,24 +26,17 @@ public class RaceChangeCriterion extends AbstractCriterion<RaceChangeCriterion.C
} }
} }
public static class Conditions extends AbstractCriterionConditions { public record Conditions (
private final Race race; Optional<LootContextPredicate> player,
Race race
public Conditions(Optional<LootContextPredicate> playerPredicate, Race race) { ) implements AbstractCriterion.Conditions {
super(playerPredicate); public static final Codec<Conditions> CODEC = RecordCodecBuilder.create(instance -> instance.group(
this.race = race; Codecs.createStrictOptionalFieldCodec(EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC, "player").forGetter(Conditions::player),
} Race.REGISTRY.getCodec().fieldOf("race").forGetter(Conditions::race)
).apply(instance, Conditions::new));
public boolean test(ServerPlayerEntity player) { public boolean test(ServerPlayerEntity player) {
return Pony.of(player).getCompositeRace().includes(race); return Pony.of(player).getCompositeRace().includes(race);
} }
@Override
public JsonObject toJson() {
JsonObject json = super.toJson();
json.addProperty("race", Race.REGISTRY.getId(race).toString());
return json;
}
} }
} }

View file

@ -11,6 +11,9 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject; import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.util.CodecUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.util.JsonHelper; import net.minecraft.util.JsonHelper;
@ -18,6 +21,13 @@ import net.minecraft.util.JsonHelper;
public record RacePredicate(Set<Race> include, Set<Race> exclude) implements Predicate<ServerPlayerEntity> { public record RacePredicate(Set<Race> include, Set<Race> exclude) implements Predicate<ServerPlayerEntity> {
public static final RacePredicate EMPTY = new RacePredicate(Set.of(), Set.of()); public static final RacePredicate EMPTY = new RacePredicate(Set.of(), Set.of());
private static final Codec<Set<Race>> RACE_SET_CODEC = CodecUtils.setOf(Race.REGISTRY.getCodec());
private static final Codec<RacePredicate> BASE_CODEC = RecordCodecBuilder.create(instance -> instance.group(
RACE_SET_CODEC.fieldOf("include").forGetter(RacePredicate::include),
RACE_SET_CODEC.fieldOf("exclude").forGetter(RacePredicate::exclude)
).apply(instance, RacePredicate::of));
public static final Codec<RacePredicate> CODEC = CodecUtils.xor(BASE_CODEC, RACE_SET_CODEC.xmap(include -> of(include, Set.of()), RacePredicate::include));
public static RacePredicate fromJson(JsonElement json) { public static RacePredicate fromJson(JsonElement json) {
if (json == null || json.isJsonNull()) { if (json == null || json.isJsonNull()) {
return EMPTY; return EMPTY;

View file

@ -3,34 +3,28 @@ package com.minelittlepony.unicopia.advancement;
import java.util.Optional; import java.util.Optional;
import java.util.function.BiConsumer; import java.util.function.BiConsumer;
import com.google.gson.JsonObject;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.util.CodecUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.fabricmc.fabric.api.util.TriState; import net.fabricmc.fabric.api.util.TriState;
import net.minecraft.advancement.criterion.AbstractCriterion; import net.minecraft.advancement.criterion.AbstractCriterion;
import net.minecraft.advancement.criterion.AbstractCriterionConditions;
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;
import net.minecraft.predicate.entity.AdvancementEntityPredicateDeserializer; import net.minecraft.predicate.entity.EntityPredicate;
import net.minecraft.predicate.entity.LootContextPredicate; import net.minecraft.predicate.entity.LootContextPredicate;
import net.minecraft.predicate.item.ItemPredicate; import net.minecraft.predicate.item.ItemPredicate;
import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.server.network.ServerPlayerEntity;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.util.JsonHelper;
import net.minecraft.util.TypeFilter; import net.minecraft.util.TypeFilter;
import net.minecraft.util.dynamic.Codecs;
public class SendViaDragonBreathScrollCriterion extends AbstractCriterion<SendViaDragonBreathScrollCriterion.Conditions> { public class SendViaDragonBreathScrollCriterion extends AbstractCriterion<SendViaDragonBreathScrollCriterion.Conditions> {
@Override @Override
protected Conditions conditionsFromJson(JsonObject json, Optional<LootContextPredicate> playerPredicate, AdvancementEntityPredicateDeserializer deserializer) { public Codec<Conditions> getConditionsCodec() {
return new Conditions(playerPredicate, return Conditions.CODEC;
ItemPredicate.fromJson(json.get("item")),
JsonHelper.getBoolean(json, "is_receiving_end", false),
json.has("recipient_name") ? Optional.of(JsonHelper.getString(json, "recipient_name")) : Optional.empty(),
json.has("recipient_present") ? TriState.of(JsonHelper.getBoolean(json, "recipient_present")) : TriState.DEFAULT,
json.has("counter") ? Optional.of(JsonHelper.getString(json, "counter")) : Optional.empty(),
RacePredicate.fromJson(json.get("race"))
);
} }
public void triggerSent(PlayerEntity player, ItemStack payload, String recipient, BiConsumer<String, Integer> counterCallback) { public void triggerSent(PlayerEntity player, ItemStack payload, String recipient, BiConsumer<String, Integer> counterCallback) {
@ -53,23 +47,24 @@ public class SendViaDragonBreathScrollCriterion extends AbstractCriterion<SendVi
} }
} }
public static class Conditions extends AbstractCriterionConditions { public record Conditions (
private final Optional<ItemPredicate> item; Optional<LootContextPredicate> player,
private final boolean isReceivingEnd; Optional<ItemPredicate> item,
private final Optional<String> recipientName; boolean isReceivingEnd,
private final TriState recipientPresent; Optional<String> recipientName,
private final Optional<String> counter; TriState recipientPresent,
private final RacePredicate races; Optional<String> counter,
RacePredicate races
public Conditions(Optional<LootContextPredicate> playerPredicate, Optional<ItemPredicate> item, boolean isReceivingEnd, Optional<String> recipient, TriState recipientPresent, Optional<String> counter, RacePredicate races) { ) implements AbstractCriterion.Conditions {
super(playerPredicate); public static final Codec<Conditions> CODEC = RecordCodecBuilder.create(instance -> instance.group(
this.item = item; Codecs.createStrictOptionalFieldCodec(EntityPredicate.LOOT_CONTEXT_PREDICATE_CODEC, "player").forGetter(Conditions::player),
this.isReceivingEnd = isReceivingEnd; ItemPredicate.CODEC.optionalFieldOf("item").forGetter(Conditions::item),
this.recipientName = recipient; Codec.BOOL.optionalFieldOf("is_receiving_end", false).forGetter(Conditions::isReceivingEnd),
this.recipientPresent = recipientPresent; Codec.STRING.optionalFieldOf("recipient_name").forGetter(Conditions::recipientName),
this.counter = counter; CodecUtils.tristateOf("recipient_present").forGetter(Conditions::recipientPresent),
this.races = races; Codec.STRING.optionalFieldOf("counter").forGetter(Conditions::counter),
} RacePredicate.CODEC.fieldOf("races").forGetter(Conditions::races)
).apply(instance, Conditions::new));
public boolean test(ServerPlayerEntity player, ItemStack payload, String recipient, boolean receiving) { public boolean test(ServerPlayerEntity player, ItemStack payload, String recipient, boolean receiving) {
return isReceivingEnd == receiving return isReceivingEnd == receiving
@ -82,18 +77,5 @@ public class SendViaDragonBreathScrollCriterion extends AbstractCriterion<SendVi
private boolean isRecipientAbsent(ServerWorld world, String recipient) { private boolean isRecipientAbsent(ServerWorld world, String recipient) {
return world.getEntitiesByType(TypeFilter.instanceOf(LivingEntity.class), e -> e.hasCustomName() && e.getCustomName().getString().equalsIgnoreCase(recipient)).isEmpty(); return world.getEntitiesByType(TypeFilter.instanceOf(LivingEntity.class), e -> e.hasCustomName() && e.getCustomName().getString().equalsIgnoreCase(recipient)).isEmpty();
} }
@Override
public JsonObject toJson() {
JsonObject json = super.toJson();
item.ifPresent(item -> json.add("item", item.toJson()));
json.add("race", races.toJson());
recipientName.ifPresent(recipient -> json.addProperty("recipient_name", recipient));
if (recipientPresent != TriState.DEFAULT) {
json.addProperty("recipient_present", recipientPresent.getBoxed());
}
counter.ifPresent(counter -> json.addProperty("counter", counter));
return json;
}
} }
} }

View file

@ -4,6 +4,7 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.server.world.ZapAppleStageStore; import com.minelittlepony.unicopia.server.world.ZapAppleStageStore;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
@ -14,9 +15,10 @@ import net.minecraft.util.math.random.Random;
import net.minecraft.world.*; import net.minecraft.world.*;
public class BaseZapAppleLeavesBlock extends LeavesBlock implements TintedBlock { public class BaseZapAppleLeavesBlock extends LeavesBlock implements TintedBlock {
public static final MapCodec<BaseZapAppleLeavesBlock> CODEC = LeavesBlock.createCodec(BaseZapAppleLeavesBlock::new);
BaseZapAppleLeavesBlock() { public static Settings settings() {
super(Settings.create() return Settings.create()
.mapColor(MapColor.PURPLE) .mapColor(MapColor.PURPLE)
.strength(500, 1200) .strength(500, 1200)
.ticksRandomly() .ticksRandomly()
@ -24,8 +26,16 @@ public class BaseZapAppleLeavesBlock extends LeavesBlock implements TintedBlock
.nonOpaque() .nonOpaque()
.allowsSpawning(BlockConstructionUtils::canSpawnOnLeaves) .allowsSpawning(BlockConstructionUtils::canSpawnOnLeaves)
.suffocates(BlockConstructionUtils::never) .suffocates(BlockConstructionUtils::never)
.blockVision(BlockConstructionUtils::never) .blockVision(BlockConstructionUtils::never);
); }
BaseZapAppleLeavesBlock(Settings settings) {
super(settings);
}
@Override
public MapCodec<? extends BaseZapAppleLeavesBlock> getCodec() {
return CODEC;
} }
@Override @Override

View file

@ -16,12 +16,8 @@ import net.minecraft.util.math.Direction;
import net.minecraft.world.BlockView; import net.minecraft.world.BlockView;
interface BlockConstructionUtils { interface BlockConstructionUtils {
static ButtonBlock woodenButton() { static ButtonBlock woodenButton(BlockSetType setType) {
return woodenButton(BlockSoundGroup.WOOD, BlockSetType.OAK); return new ButtonBlock(setType, 30, AbstractBlock.Settings.create().noCollision().strength(0.5f).pistonBehavior(PistonBehavior.DESTROY));
}
static ButtonBlock woodenButton(BlockSoundGroup soundGroup, BlockSetType setType) {
return new ButtonBlock(AbstractBlock.Settings.create().noCollision().strength(0.5f).pistonBehavior(PistonBehavior.DESTROY).sounds(soundGroup), setType, 30, true);
} }
static boolean never(BlockState state, BlockView world, BlockPos pos, EntityType<?> type) { static boolean never(BlockState state, BlockView world, BlockPos pos, EntityType<?> type) {

View file

@ -6,6 +6,8 @@ import com.minelittlepony.unicopia.EquineContext;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockSetType; import net.minecraft.block.BlockSetType;
@ -24,9 +26,18 @@ import net.minecraft.world.World;
import net.minecraft.world.event.GameEvent; import net.minecraft.world.event.GameEvent;
public class CrystalDoorBlock extends DoorBlock { public class CrystalDoorBlock extends DoorBlock {
public static final MapCodec<CrystalDoorBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
BlockSetType.CODEC.fieldOf("block_set_type").forGetter(CrystalDoorBlock::getBlockSetType),
DoorBlock.createSettingsCodec()
).apply(instance, CrystalDoorBlock::new));
public CrystalDoorBlock(Settings settings, BlockSetType blockSet) { public CrystalDoorBlock(BlockSetType blockSet, Settings settings) {
super(settings, blockSet); super(blockSet, settings);
}
@Override
public MapCodec<? extends CrystalDoorBlock> getCodec() {
return CODEC;
} }
@Override @Override

View file

@ -8,6 +8,9 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.item.BedsheetsItem; import com.minelittlepony.unicopia.item.BedsheetsItem;
import com.minelittlepony.unicopia.util.VoxelShapeUtil; import com.minelittlepony.unicopia.util.VoxelShapeUtil;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.BedBlock; import net.minecraft.block.BedBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -30,6 +33,10 @@ import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
public class FancyBedBlock extends BedBlock { public class FancyBedBlock extends BedBlock {
public static final MapCodec<FancyBedBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.STRING.fieldOf("base").forGetter(b -> b.base),
BedBlock.createSettingsCodec()
).apply(instance, FancyBedBlock::new));
private static final List<Function<Direction, VoxelShape>> SHAPES = List.of( private static final List<Function<Direction, VoxelShape>> SHAPES = List.of(
VoxelShapeUtil.rotator(VoxelShapes.union( VoxelShapeUtil.rotator(VoxelShapes.union(
createCuboidShape(0, 3, 1, 16, 9, 16), createCuboidShape(0, 3, 1, 16, 9, 16),
@ -52,6 +59,12 @@ public class FancyBedBlock extends BedBlock {
this.base = base; this.base = base;
} }
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public MapCodec<BedBlock> getCodec() {
return (MapCodec)CODEC;
}
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return SHAPES.get(state.get(PART).ordinal()).apply(BedBlock.getOppositePartDirection(state)); return SHAPES.get(state.get(PART).ordinal()).apply(BedBlock.getOppositePartDirection(state));

View file

@ -2,6 +2,8 @@ package com.minelittlepony.unicopia.block;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -14,10 +16,18 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
public class FrostedObsidianBlock extends FrostedIceBlock { public class FrostedObsidianBlock extends FrostedIceBlock {
public static final MapCodec<FrostedObsidianBlock> CODEC = createCodec(FrostedObsidianBlock::new);
public FrostedObsidianBlock(Settings settings) { public FrostedObsidianBlock(Settings settings) {
super(settings); super(settings);
} }
@SuppressWarnings({ "rawtypes", "unchecked" })
@Override
public MapCodec<FrostedIceBlock> getCodec() {
return (MapCodec)CODEC;
}
@Override @Override
public void afterBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack) { public void afterBreak(World world, PlayerEntity player, BlockPos pos, BlockState state, @Nullable BlockEntity blockEntity, ItemStack stack) {
player.incrementStat(Stats.MINED.getOrCreateStat(this)); player.incrementStat(Stats.MINED.getOrCreateStat(this));

View file

@ -8,10 +8,15 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.ability.EarthPonyKickAbility.Buckable; import com.minelittlepony.unicopia.ability.EarthPonyKickAbility.Buckable;
import com.minelittlepony.unicopia.compat.seasons.FertilizableUtil; import com.minelittlepony.unicopia.compat.seasons.FertilizableUtil;
import com.minelittlepony.unicopia.util.CodecUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry; import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.BlockSoundGroup; import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
@ -25,6 +30,12 @@ import net.minecraft.world.*;
import net.minecraft.world.event.GameEvent; import net.minecraft.world.event.GameEvent;
public class FruitBearingBlock extends LeavesBlock implements TintedBlock, Buckable { public class FruitBearingBlock extends LeavesBlock implements TintedBlock, Buckable {
public static final MapCodec<FruitBearingBlock> CODEC = RecordCodecBuilder.<FruitBearingBlock>mapCodec(instance -> instance.group(
Codec.INT.fieldOf("overlay").forGetter(b -> b.overlay),
CodecUtils.supplierOf(Registries.BLOCK.getCodec()).fieldOf("fruit").forGetter(b -> b.fruit),
CodecUtils.supplierOf(ItemStack.CODEC).fieldOf("rotten_fruit").forGetter(b -> b.rottenFruitSupplier),
BedBlock.createSettingsCodec()
).apply(instance, FruitBearingBlock::new));
public static final IntProperty AGE = Properties.AGE_25; public static final IntProperty AGE = Properties.AGE_25;
public static final int WITHER_AGE = 15; public static final int WITHER_AGE = 15;
public static final EnumProperty<Stage> STAGE = EnumProperty.of("stage", Stage.class); public static final EnumProperty<Stage> STAGE = EnumProperty.of("stage", Stage.class);
@ -36,7 +47,7 @@ public class FruitBearingBlock extends LeavesBlock implements TintedBlock, Bucka
private final int overlay; private final int overlay;
public FruitBearingBlock(Settings settings, int overlay, Supplier<Block> fruit, Supplier<ItemStack> rottenFruitSupplier) { public FruitBearingBlock(int overlay, Supplier<Block> fruit, Supplier<ItemStack> rottenFruitSupplier, Settings settings) {
super(settings super(settings
.ticksRandomly() .ticksRandomly()
.nonOpaque() .nonOpaque()
@ -51,6 +62,11 @@ public class FruitBearingBlock extends LeavesBlock implements TintedBlock, Bucka
FlammableBlockRegistry.getDefaultInstance().add(this, 30, 60); FlammableBlockRegistry.getDefaultInstance().add(this, 30, 60);
} }
@Override
public MapCodec<? extends FruitBearingBlock> getCodec() {
return CODEC;
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder); super.appendProperties(builder);

View file

@ -3,11 +3,15 @@ package com.minelittlepony.unicopia.block;
import java.util.List; import java.util.List;
import com.minelittlepony.unicopia.ability.EarthPonyKickAbility.Buckable; import com.minelittlepony.unicopia.ability.EarthPonyKickAbility.Buckable;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.fabricmc.fabric.api.registry.FlammableBlockRegistry; import net.fabricmc.fabric.api.registry.FlammableBlockRegistry;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.piston.PistonBehavior; import net.minecraft.block.piston.PistonBehavior;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.registry.Registries;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.BlockSoundGroup; import net.minecraft.sound.BlockSoundGroup;
import net.minecraft.util.math.*; import net.minecraft.util.math.*;
@ -19,6 +23,16 @@ public class FruitBlock extends Block implements Buckable {
public static final int DEFAULT_FRUIT_SIZE = 5; public static final int DEFAULT_FRUIT_SIZE = 5;
public static final double DEFAULT_STEM_OFFSET = 2.6F; public static final double DEFAULT_STEM_OFFSET = 2.6F;
public static final VoxelShape DEFAULT_SHAPE = createFruitShape(DEFAULT_STEM_OFFSET, DEFAULT_FRUIT_SIZE); public static final VoxelShape DEFAULT_SHAPE = createFruitShape(DEFAULT_STEM_OFFSET, DEFAULT_FRUIT_SIZE);
public static final MapCodec<FruitBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Direction.CODEC.fieldOf("attachment_face").forGetter(b -> b.attachmentFace),
Registries.BLOCK.getCodec().fieldOf("stem").forGetter(b -> b.stem),
RecordCodecBuilder.create(i -> i.group(
Codec.DOUBLE.fieldOf("stem_offset").forGetter(b -> (double)0),
Codec.DOUBLE.fieldOf("fruit_offset").forGetter(b -> (double)0)
).apply(i, FruitBlock::createFruitShape)).fieldOf("shape").forGetter(b -> b.shape),
Codec.BOOL.fieldOf("flammable").forGetter(b -> false),
BedBlock.createSettingsCodec()
).apply(instance, FruitBlock::new));
private final Direction attachmentFace; private final Direction attachmentFace;
private final Block stem; private final Block stem;
@ -31,11 +45,16 @@ public class FruitBlock extends Block implements Buckable {
return createCuboidShape(min, top - fruitSize, min, max, top, max); return createCuboidShape(min, top - fruitSize, min, max, top, max);
} }
public FruitBlock(Settings settings, Direction attachmentFace, Block stem, VoxelShape shape) { @Override
this(settings.sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.DESTROY), attachmentFace, stem, shape, true); public MapCodec<? extends FruitBlock> getCodec() {
return CODEC;
} }
public FruitBlock(Settings settings, Direction attachmentFace, Block stem, VoxelShape shape, boolean flammable) { public FruitBlock(Direction attachmentFace, Block stem, VoxelShape shape, Settings settings) {
this(attachmentFace, stem, shape, true, settings.sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.DESTROY));
}
public FruitBlock(Direction attachmentFace, Block stem, VoxelShape shape, boolean flammable, Settings settings) {
super(settings.nonOpaque().suffocates(BlockConstructionUtils::never).blockVision(BlockConstructionUtils::never)); super(settings.nonOpaque().suffocates(BlockConstructionUtils::never).blockVision(BlockConstructionUtils::never));
this.attachmentFace = attachmentFace; this.attachmentFace = attachmentFace;
this.stem = stem; this.stem = stem;

View file

@ -3,13 +3,18 @@ package com.minelittlepony.unicopia.block;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.util.CodecUtils;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.BedBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.SnowBlock; import net.minecraft.block.SnowBlock;
import net.minecraft.block.SpreadableBlock; import net.minecraft.block.SpreadableBlock;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
import net.minecraft.registry.Registries;
import net.minecraft.registry.tag.FluidTags; import net.minecraft.registry.tag.FluidTags;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundCategory;
@ -21,14 +26,23 @@ import net.minecraft.world.WorldView;
import net.minecraft.world.chunk.light.ChunkLightProvider; import net.minecraft.world.chunk.light.ChunkLightProvider;
public class GrowableBlock extends SpreadableBlock { public class GrowableBlock extends SpreadableBlock {
public static final MapCodec<GrowableBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
CodecUtils.supplierOf(Registries.BLOCK.getCodec()).fieldOf("dead").forGetter(b -> b.dead),
BedBlock.createSettingsCodec()
).apply(instance, GrowableBlock::new));
private final Supplier<Block> dead; private final Supplier<Block> dead;
protected GrowableBlock(Settings settings, Supplier<Block> converted) { protected GrowableBlock(Supplier<Block> converted, Settings settings) {
super(settings); super(settings);
this.dead = converted; this.dead = converted;
} }
@Override
protected MapCodec<? extends GrowableBlock> getCodec() {
return CODEC;
}
@Override @Override
public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) { public void randomDisplayTick(BlockState state, World world, BlockPos pos, Random random) {
super.randomDisplayTick(state, world, pos, random); super.randomDisplayTick(state, world, pos, random);

View file

@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.ParticleUtils;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -29,6 +30,7 @@ import net.minecraft.world.World;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
public class HiveBlock extends ConnectingBlock { public class HiveBlock extends ConnectingBlock {
public static final MapCodec<HiveBlock> CODEC = createCodec(HiveBlock::new);
static final BooleanProperty AWAKE = BooleanProperty.of("awake"); static final BooleanProperty AWAKE = BooleanProperty.of("awake");
static final Collection<BooleanProperty> PROPERTIES = FACING_PROPERTIES.values(); static final Collection<BooleanProperty> PROPERTIES = FACING_PROPERTIES.values();
@ -40,6 +42,11 @@ public class HiveBlock extends ConnectingBlock {
}); });
} }
@Override
protected MapCodec<? extends HiveBlock> getCodec() {
return CODEC;
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(PROPERTIES.toArray(Property[]::new)); builder.add(PROPERTIES.toArray(Property[]::new));

View file

@ -1,5 +1,7 @@
package com.minelittlepony.unicopia.block; package com.minelittlepony.unicopia.block;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.FacingBlock; import net.minecraft.block.FacingBlock;
@ -9,10 +11,17 @@ import net.minecraft.util.BlockMirror;
import net.minecraft.util.BlockRotation; import net.minecraft.util.BlockRotation;
public class OrientedBlock extends FacingBlock { public class OrientedBlock extends FacingBlock {
public static final MapCodec<OrientedBlock> CODEC = createCodec(OrientedBlock::new);
protected OrientedBlock(Settings settings) { protected OrientedBlock(Settings settings) {
super(settings); super(settings);
} }
@Override
protected MapCodec<? extends OrientedBlock> getCodec() {
return CODEC;
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(FACING); builder.add(FACING);

View file

@ -2,7 +2,10 @@ package com.minelittlepony.unicopia.block;
import com.minelittlepony.unicopia.*; import com.minelittlepony.unicopia.*;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.util.CodecUtils;
import com.minelittlepony.unicopia.util.SoundEmitter; import com.minelittlepony.unicopia.util.SoundEmitter;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@ -28,6 +31,12 @@ import net.minecraft.world.*;
import net.minecraft.world.event.GameEvent; import net.minecraft.world.event.GameEvent;
public class PieBlock extends Block implements Waterloggable { public class PieBlock extends Block implements Waterloggable {
public static final MapCodec<PieBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
CodecUtils.ITEM.fieldOf("slice_item").forGetter(b -> b.sliceItem),
CodecUtils.ITEM.fieldOf("normal_item").forGetter(b -> b.normalItem),
CodecUtils.ITEM.fieldOf("stomped_item").forGetter(b -> b.stompedItem),
BedBlock.createSettingsCodec()
).apply(instance, PieBlock::new));
public static final int MAX_BITES = 3; public static final int MAX_BITES = 3;
public static final IntProperty BITES = IntProperty.of("bites", 0, MAX_BITES); public static final IntProperty BITES = IntProperty.of("bites", 0, MAX_BITES);
public static final BooleanProperty STOMPED = BooleanProperty.of("stomped"); public static final BooleanProperty STOMPED = BooleanProperty.of("stomped");
@ -50,7 +59,7 @@ public class PieBlock extends Block implements Waterloggable {
private final ItemConvertible normalItem; private final ItemConvertible normalItem;
private final ItemConvertible stompedItem; private final ItemConvertible stompedItem;
public PieBlock(Settings settings, ItemConvertible sliceItem, ItemConvertible normalItem, ItemConvertible stompedItem) { public PieBlock(ItemConvertible sliceItem, ItemConvertible normalItem, ItemConvertible stompedItem, Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(STOMPED, false).with(WATERLOGGED, false)); setDefaultState(getDefaultState().with(STOMPED, false).with(WATERLOGGED, false));
this.sliceItem = sliceItem; this.sliceItem = sliceItem;
@ -58,6 +67,11 @@ public class PieBlock extends Block implements Waterloggable {
this.stompedItem = stompedItem; this.stompedItem = stompedItem;
} }
@Override
protected MapCodec<? extends PieBlock> getCodec() {
return CODEC;
}
@Deprecated @Deprecated
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
@ -127,7 +141,7 @@ public class PieBlock extends Block implements Waterloggable {
} }
@Override @Override
public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) { public ItemStack getPickStack(WorldView world, BlockPos pos, BlockState state) {
return (state.get(STOMPED) ? stompedItem : normalItem).asItem().getDefaultStack(); return (state.get(STOMPED) ? stompedItem : normalItem).asItem().getDefaultStack();
} }

View file

@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.block;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -25,6 +26,7 @@ import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView; import net.minecraft.world.WorldView;
public class PileBlock extends Block implements Waterloggable { public class PileBlock extends Block implements Waterloggable {
public static final MapCodec<PileBlock> CODEC = createCodec(settings -> new PileBlock(settings, PileBlock.MYSTERIOUS_EGG_SHAPES));
public static final int MAX_COUNT = 3; public static final int MAX_COUNT = 3;
public static final IntProperty COUNT = IntProperty.of("count", 1, MAX_COUNT); public static final IntProperty COUNT = IntProperty.of("count", 1, MAX_COUNT);
public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED; public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;
@ -50,6 +52,11 @@ public class PileBlock extends Block implements Waterloggable {
this.shapes = shapes; this.shapes = shapes;
} }
@Override
protected MapCodec<? extends PileBlock> getCodec() {
return CODEC;
}
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
Vec3d offset = state.getModelOffset(world, pos); Vec3d offset = state.getModelOffset(world, pos);

View file

@ -2,6 +2,7 @@ package com.minelittlepony.unicopia.block;
import com.minelittlepony.unicopia.compat.seasons.FertilizableUtil; import com.minelittlepony.unicopia.compat.seasons.FertilizableUtil;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -23,6 +24,7 @@ import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView; import net.minecraft.world.WorldView;
public class PineappleCropBlock extends CropBlock { public class PineappleCropBlock extends CropBlock {
public static final MapCodec<PineappleCropBlock> CODEC = createCodec(PineappleCropBlock::new);
public static final EnumProperty<BlockHalf> HALF = Properties.BLOCK_HALF; public static final EnumProperty<BlockHalf> HALF = Properties.BLOCK_HALF;
public static final BooleanProperty WILD = BooleanProperty.of("wild"); public static final BooleanProperty WILD = BooleanProperty.of("wild");
@ -31,9 +33,13 @@ public class PineappleCropBlock extends CropBlock {
setDefaultState(getDefaultState().with(HALF, BlockHalf.BOTTOM).with(WILD, false)); setDefaultState(getDefaultState().with(HALF, BlockHalf.BOTTOM).with(WILD, false));
} }
@Override
public MapCodec<? extends PineappleCropBlock> getCodec() {
return CODEC;
}
@Override @Override
public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) { public ItemStack getPickStack(WorldView world, BlockPos pos, BlockState state) {
if (state.get(HALF) == BlockHalf.TOP) { if (state.get(HALF) == BlockHalf.TOP) {
return UItems.PINEAPPLE.getDefaultStack(); return UItems.PINEAPPLE.getDefaultStack();
} }

View file

@ -6,6 +6,7 @@ import com.minelittlepony.unicopia.EquineContext;
import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.EquinePredicates;
import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.Race;
import com.minelittlepony.unicopia.item.UItems; import com.minelittlepony.unicopia.item.UItems;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.CropBlock; import net.minecraft.block.CropBlock;
@ -20,6 +21,7 @@ import net.minecraft.util.shape.VoxelShapes;
import net.minecraft.world.*; import net.minecraft.world.*;
public class RockCropBlock extends CropBlock { public class RockCropBlock extends CropBlock {
public static final MapCodec<RockCropBlock> CODEC = createCodec(RockCropBlock::new);
private static final VoxelShape[] AGE_TO_SHAPE = new VoxelShape[] { private static final VoxelShape[] AGE_TO_SHAPE = new VoxelShape[] {
VoxelShapes.union( VoxelShapes.union(
createCuboidShape(7, -1, 11, 8, 0, 12), createCuboidShape(7, -1, 11, 8, 0, 12),
@ -67,6 +69,11 @@ public class RockCropBlock extends CropBlock {
super(settings); super(settings);
} }
@Override
public MapCodec<? extends RockCropBlock> getCodec() {
return CODEC;
}
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return AGE_TO_SHAPE[state.get(getAgeProperty())]; return AGE_TO_SHAPE[state.get(getAgeProperty())];

View file

@ -5,9 +5,14 @@ import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.compat.seasons.FertilizableUtil; import com.minelittlepony.unicopia.compat.seasons.FertilizableUtil;
import com.minelittlepony.unicopia.util.CodecUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemConvertible;
import net.minecraft.registry.Registries;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.state.StateManager; import net.minecraft.state.StateManager;
import net.minecraft.state.property.IntProperty; import net.minecraft.state.property.IntProperty;
@ -18,6 +23,18 @@ import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.*; import net.minecraft.world.*;
public class SegmentedCropBlock extends CropBlock implements SegmentedBlock { public class SegmentedCropBlock extends CropBlock implements SegmentedBlock {
private static final Codec<Supplier<SegmentedCropBlock>> SEGMENT_CODEC = CodecUtils.supplierOf(Registries.BLOCK.getCodec().xmap(
b -> (SegmentedCropBlock)b,
b -> (Block)b
));
public static final MapCodec<SegmentedCropBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.INT.fieldOf("max_age").forGetter(b -> b.getAgeProperty().getValues().stream().mapToInt(i -> i).max().orElse(0)),
Codec.INT.fieldOf("progression_age").forGetter(b -> b.progressionAge),
CodecUtils.ITEM.fieldOf("seeds").forGetter(b -> b.seeds),
SEGMENT_CODEC.optionalFieldOf("prev", null).forGetter(b -> b.prevSegmentSupplier),
SEGMENT_CODEC.optionalFieldOf("next", null).forGetter(b -> b.nextSegmentSupplier),
BedBlock.createSettingsCodec()
).apply(instance, SegmentedCropBlock::create));
static final float BASE_GROWTH_CHANCE = /*1 in */ 50F /* chance, half the speed of regular crops */; static final float BASE_GROWTH_CHANCE = /*1 in */ 50F /* chance, half the speed of regular crops */;
@ -30,10 +47,10 @@ public class SegmentedCropBlock extends CropBlock implements SegmentedBlock {
private final int progressionAge; private final int progressionAge;
public static SegmentedCropBlock create(final int maxAge, int progressionAge, Block.Settings settings, public static SegmentedCropBlock create(final int maxAge, int progressionAge,
ItemConvertible seeds, ItemConvertible seeds,
@Nullable Supplier<SegmentedCropBlock> prevSegmentSupplier, @Nullable Supplier<SegmentedCropBlock> prevSegmentSupplier,
@Nullable Supplier<SegmentedCropBlock> nextSegmentSupplier) { @Nullable Supplier<SegmentedCropBlock> nextSegmentSupplier, Block.Settings settings) {
final IntProperty age = IntProperty.of("age", 0, maxAge); final IntProperty age = IntProperty.of("age", 0, maxAge);
return new SegmentedCropBlock(progressionAge, settings, seeds, prevSegmentSupplier, nextSegmentSupplier) { return new SegmentedCropBlock(progressionAge, settings, seeds, prevSegmentSupplier, nextSegmentSupplier) {
@ -66,11 +83,16 @@ public class SegmentedCropBlock extends CropBlock implements SegmentedBlock {
} }
public SegmentedCropBlock createNext(int progressionAge) { public SegmentedCropBlock createNext(int progressionAge) {
SegmentedCropBlock next = create(getMaxAge() - this.progressionAge, progressionAge, Settings.copy(this), seeds, () -> this, null); SegmentedCropBlock next = create(getMaxAge() - this.progressionAge, progressionAge, seeds, () -> this, null, Settings.copy(this));
nextSegmentSupplier = () -> next; nextSegmentSupplier = () -> next;
return next; return next;
} }
@Override
public MapCodec<? extends SegmentedCropBlock> getCodec() {
return CODEC;
}
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
BlockPos tip = getTip(world, pos); BlockPos tip = getTip(world, pos);

View file

@ -2,6 +2,8 @@ package com.minelittlepony.unicopia.block;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.ShapeContext; import net.minecraft.block.ShapeContext;
@ -22,6 +24,7 @@ import net.minecraft.world.BlockView;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
public class ShellsBlock extends Block implements Waterloggable { public class ShellsBlock extends Block implements Waterloggable {
public static final MapCodec<ShellsBlock> CODEC = createCodec(ShellsBlock::new);
public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED; public static final BooleanProperty WATERLOGGED = Properties.WATERLOGGED;
public static final IntProperty COUNT = IntProperty.of("count", 1, 4); public static final IntProperty COUNT = IntProperty.of("count", 1, 4);
@ -31,6 +34,11 @@ public class ShellsBlock extends Block implements Waterloggable {
super(settings); super(settings);
} }
@Override
protected MapCodec<? extends ShellsBlock> getCodec() {
return CODEC;
}
@Override @Override
@Deprecated @Deprecated
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {

View file

@ -6,6 +6,7 @@ import java.util.Locale;
import org.joml.Vector3f; import org.joml.Vector3f;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
@ -40,6 +41,7 @@ import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView; import net.minecraft.world.WorldView;
public class SlimePustuleBlock extends Block { public class SlimePustuleBlock extends Block {
public static final MapCodec<SlimePustuleBlock> CODEC = createCodec(SlimePustuleBlock::new);
private static final EnumProperty<Shape> SHAPE = EnumProperty.of("shape", Shape.class); private static final EnumProperty<Shape> SHAPE = EnumProperty.of("shape", Shape.class);
private static final BooleanProperty POWERED = Properties.POWERED; private static final BooleanProperty POWERED = Properties.POWERED;
private static final Direction[] DIRECTIONS = Arrays.stream(Direction.values()) private static final Direction[] DIRECTIONS = Arrays.stream(Direction.values())
@ -65,6 +67,11 @@ public class SlimePustuleBlock extends Block {
setDefaultState(getDefaultState().with(SHAPE, Shape.DRIP).with(POWERED, false)); setDefaultState(getDefaultState().with(SHAPE, Shape.DRIP).with(POWERED, false));
} }
@Override
protected MapCodec<? extends SlimePustuleBlock> getCodec() {
return CODEC;
}
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return switch (state.get(SHAPE)) { return switch (state.get(SHAPE)) {
@ -113,7 +120,7 @@ public class SlimePustuleBlock extends Block {
} }
@Override @Override
public void onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) { public BlockState onBreak(World world, BlockPos pos, BlockState state, PlayerEntity player) {
if (state.get(SHAPE) == Shape.POD) { if (state.get(SHAPE) == Shape.POD) {
world.getOtherEntities(null, new Box(pos).expand(1)).forEach(entity -> { world.getOtherEntities(null, new Box(pos).expand(1)).forEach(entity -> {
entity.damage(entity.getDamageSources().inFire(), 2); entity.damage(entity.getDamageSources().inFire(), 2);
@ -147,9 +154,11 @@ public class SlimePustuleBlock extends Block {
world.random.nextGaussian() * 1.5F world.random.nextGaussian() * 1.5F
); );
} }
} else {
super.onBreak(world, pos, state, player); return state;
} }
return super.onBreak(world, pos, state, player);
} }
@Override @Override

View file

@ -2,6 +2,8 @@ package com.minelittlepony.unicopia.block;
import org.joml.Vector3f; import org.joml.Vector3f;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
import net.minecraft.block.SideShapeType; import net.minecraft.block.SideShapeType;
@ -20,10 +22,17 @@ import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView; import net.minecraft.world.WorldView;
public class SpikesBlock extends OrientedBlock { public class SpikesBlock extends OrientedBlock {
public static final MapCodec<SpikesBlock> CODEC = createCodec(SpikesBlock::new);
public SpikesBlock(Settings settings) { public SpikesBlock(Settings settings) {
super(settings); super(settings);
} }
@Override
protected MapCodec<? extends SpikesBlock> getCodec() {
return CODEC;
}
@Deprecated @Deprecated
@Override @Override
public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) { public void onEntityCollision(BlockState state, World world, BlockPos pos, Entity entity) {

View file

@ -4,6 +4,11 @@ import java.util.function.Supplier;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.util.CodecUtils;
import com.mojang.serialization.Codec;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.piston.PistonBehavior; import net.minecraft.block.piston.PistonBehavior;
import net.minecraft.item.ItemConvertible; import net.minecraft.item.ItemConvertible;
@ -17,6 +22,13 @@ import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.*; import net.minecraft.world.*;
public class SproutBlock extends CropBlock implements TintedBlock { public class SproutBlock extends CropBlock implements TintedBlock {
public static final MapCodec<SproutBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
Codec.INT.fieldOf("overlay").forGetter(b -> b.overlay),
CodecUtils.ITEM.fieldOf("seeds").forGetter(b -> b.seeds),
CodecUtils.supplierOf(BlockState.CODEC).fieldOf("mature_state").forGetter(b -> b.matureState),
BedBlock.createSettingsCodec()
).apply(instance, SproutBlock::new));
private static final VoxelShape[] AGE_TO_SHAPE = new VoxelShape[]{ private static final VoxelShape[] AGE_TO_SHAPE = new VoxelShape[]{
Block.createCuboidShape(7, 0, 7, 9, 2, 9), Block.createCuboidShape(7, 0, 7, 9, 2, 9),
Block.createCuboidShape(7, 0, 7, 9, 4, 9), Block.createCuboidShape(7, 0, 7, 9, 4, 9),
@ -28,24 +40,33 @@ public class SproutBlock extends CropBlock implements TintedBlock {
Block.createCuboidShape(7, 0, 7, 9, 16, 9) Block.createCuboidShape(7, 0, 7, 9, 16, 9)
}; };
public static Settings settings() {
return Settings.create()
.noCollision()
.ticksRandomly()
.breakInstantly()
.sounds(BlockSoundGroup.STEM)
.pistonBehavior(PistonBehavior.DESTROY);
}
private final ItemConvertible seeds; private final ItemConvertible seeds;
private final Supplier<BlockState> matureState; private final Supplier<BlockState> matureState;
private final int overlay; private final int overlay;
public SproutBlock(int overlay, ItemConvertible seeds, Supplier<BlockState> matureState) { public SproutBlock(int overlay, ItemConvertible seeds, Supplier<BlockState> matureState, Settings settings) {
super(Settings.create() super(settings);
.noCollision()
.ticksRandomly()
.breakInstantly()
.sounds(BlockSoundGroup.STEM)
.pistonBehavior(PistonBehavior.DESTROY));
this.seeds = seeds; this.seeds = seeds;
this.matureState = matureState; this.matureState = matureState;
this.overlay = overlay; this.overlay = overlay;
} }
@Override
public MapCodec<? extends SproutBlock> getCodec() {
return CODEC;
}
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {
return AGE_TO_SHAPE[state.get(getAgeProperty())]; return AGE_TO_SHAPE[state.get(getAgeProperty())];
@ -75,7 +96,7 @@ public class SproutBlock extends CropBlock implements TintedBlock {
} }
@Override @Override
public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) { public ItemStack getPickStack(WorldView world, BlockPos pos, BlockState state) {
return new ItemStack(seeds.asItem()); return new ItemStack(seeds.asItem());
} }

View file

@ -1,5 +1,8 @@
package com.minelittlepony.unicopia.block; package com.minelittlepony.unicopia.block;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.BlockSetType; import net.minecraft.block.BlockSetType;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -10,9 +13,18 @@ import net.minecraft.util.math.Direction;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
public class StableDoorBlock extends DoorBlock { public class StableDoorBlock extends DoorBlock {
public static final MapCodec<StableDoorBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
BlockSetType.CODEC.fieldOf("block_set_type").forGetter(StableDoorBlock::getBlockSetType),
DoorBlock.createSettingsCodec()
).apply(instance, StableDoorBlock::new));
public StableDoorBlock(Settings settings, BlockSetType blockSet) { public StableDoorBlock(BlockSetType blockSet, Settings settings) {
super(settings, blockSet); super(blockSet, settings);
}
@Override
public MapCodec<? extends StableDoorBlock> getCodec() {
return CODEC;
} }
@Override @Override

View file

@ -4,14 +4,19 @@ import java.util.Collection;
import java.util.function.Supplier; import java.util.function.Supplier;
import com.minelittlepony.unicopia.ability.EarthPonyGrowAbility; import com.minelittlepony.unicopia.ability.EarthPonyGrowAbility;
import com.minelittlepony.unicopia.entity.mob.UEntities; import com.minelittlepony.unicopia.entity.mob.UEntities;
import com.minelittlepony.unicopia.util.CodecUtils;
import com.minelittlepony.unicopia.util.VecHelper; import com.minelittlepony.unicopia.util.VecHelper;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.BedBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.ConnectingBlock; import net.minecraft.block.ConnectingBlock;
import net.minecraft.block.Fertilizable; import net.minecraft.block.Fertilizable;
import net.minecraft.entity.SpawnReason; import net.minecraft.entity.SpawnReason;
import net.minecraft.particle.ParticleTypes; import net.minecraft.particle.ParticleTypes;
import net.minecraft.registry.Registries;
import net.minecraft.registry.tag.BlockTags; import net.minecraft.registry.tag.BlockTags;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
import net.minecraft.state.StateManager; import net.minecraft.state.StateManager;
@ -29,6 +34,10 @@ import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView; import net.minecraft.world.WorldView;
public class ThornBlock extends ConnectingBlock implements EarthPonyGrowAbility.Growable, Fertilizable { public class ThornBlock extends ConnectingBlock implements EarthPonyGrowAbility.Growable, Fertilizable {
public static final MapCodec<ThornBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
CodecUtils.supplierOf(Registries.BLOCK.getCodec()).fieldOf("bud").forGetter(b -> b.bud),
BedBlock.createSettingsCodec()
).apply(instance, ThornBlock::new));
static final Collection<BooleanProperty> PROPERTIES = FACING_PROPERTIES.values(); static final Collection<BooleanProperty> PROPERTIES = FACING_PROPERTIES.values();
static final DirectionProperty FACING = Properties.FACING; static final DirectionProperty FACING = Properties.FACING;
static final int MAX_DISTANCE = 25; static final int MAX_DISTANCE = 25;
@ -38,7 +47,7 @@ public class ThornBlock extends ConnectingBlock implements EarthPonyGrowAbility.
private final Supplier<Block> bud; private final Supplier<Block> bud;
public ThornBlock(Settings settings, Supplier<Block> bud) { public ThornBlock(Supplier<Block> bud, Settings settings) {
super(0.125F, settings); super(0.125F, settings);
this.bud = bud; this.bud = bud;
PROPERTIES.forEach(property -> setDefaultState(getDefaultState().with(property, false))); PROPERTIES.forEach(property -> setDefaultState(getDefaultState().with(property, false)));
@ -50,6 +59,11 @@ public class ThornBlock extends ConnectingBlock implements EarthPonyGrowAbility.
); );
} }
@Override
public MapCodec<? extends ThornBlock> getCodec() {
return CODEC;
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(PROPERTIES.toArray(Property[]::new)); builder.add(PROPERTIES.toArray(Property[]::new));

View file

@ -5,7 +5,10 @@ import java.util.stream.Stream;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.ability.EarthPonyGrowAbility; import com.minelittlepony.unicopia.ability.EarthPonyGrowAbility;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.BedBlock;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks; import net.minecraft.block.Blocks;
@ -25,18 +28,27 @@ import net.minecraft.world.WorldAccess;
import net.minecraft.world.WorldView; import net.minecraft.world.WorldView;
public class ThornBudBlock extends Block implements EarthPonyGrowAbility.Growable, Fertilizable { public class ThornBudBlock extends Block implements EarthPonyGrowAbility.Growable, Fertilizable {
public static final MapCodec<ThornBudBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
BlockState.CODEC.fieldOf("branch_state").forGetter(b -> b.branchState),
BedBlock.createSettingsCodec()
).apply(instance, ThornBudBlock::new));
static final DirectionProperty FACING = Properties.FACING; static final DirectionProperty FACING = Properties.FACING;
static final int MAX_DISTANCE = 25; static final int MAX_DISTANCE = 25;
static final IntProperty DISTANCE = IntProperty.of("distance", 0, MAX_DISTANCE); static final IntProperty DISTANCE = IntProperty.of("distance", 0, MAX_DISTANCE);
private final BlockState branchState; private final BlockState branchState;
public ThornBudBlock(Settings settings, BlockState branchState) { public ThornBudBlock(BlockState branchState, Settings settings) {
super(settings); super(settings);
setDefaultState(getDefaultState().with(FACING, Direction.DOWN).with(DISTANCE, 0)); setDefaultState(getDefaultState().with(FACING, Direction.DOWN).with(DISTANCE, 0));
this.branchState = branchState; this.branchState = branchState;
} }
@Override
protected MapCodec<? extends ThornBudBlock> getCodec() {
return CODEC;
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
builder.add(FACING, DISTANCE); builder.add(FACING, DISTANCE);

View file

@ -57,17 +57,17 @@ public interface UBlocks {
Block FROSTED_OBSIDIAN = register("frosted_obsidian", new FrostedObsidianBlock(FabricBlockSettings.copy(Blocks.OBSIDIAN).ticksRandomly())); Block FROSTED_OBSIDIAN = register("frosted_obsidian", new FrostedObsidianBlock(FabricBlockSettings.copy(Blocks.OBSIDIAN).ticksRandomly()));
Block ZAP_LOG = register("zap_log", new ZapAppleLogBlock(Blocks.OAK_LOG, MapColor.GRAY, MapColor.DEEPSLATE_GRAY), ItemGroups.BUILDING_BLOCKS); Block ZAP_LOG = register("zap_log", new ZapAppleLogBlock(Blocks.OAK_LOG.getDefaultState(), ZapAppleLogBlock.settings(MapColor.GRAY, MapColor.DEEPSLATE_GRAY)), ItemGroups.BUILDING_BLOCKS);
Block ZAP_WOOD = register("zap_wood", new ZapAppleLogBlock(Blocks.OAK_WOOD, MapColor.DEEPSLATE_GRAY, MapColor.DEEPSLATE_GRAY), ItemGroups.BUILDING_BLOCKS); Block ZAP_WOOD = register("zap_wood", new ZapAppleLogBlock(Blocks.OAK_WOOD.getDefaultState(), ZapAppleLogBlock.settings(MapColor.DEEPSLATE_GRAY, MapColor.DEEPSLATE_GRAY)), ItemGroups.BUILDING_BLOCKS);
Block STRIPPED_ZAP_LOG = register("stripped_zap_log", new ZapAppleLogBlock(Blocks.STRIPPED_OAK_LOG, MapColor.LIGHT_GRAY, MapColor.GRAY), ItemGroups.BUILDING_BLOCKS); Block STRIPPED_ZAP_LOG = register("stripped_zap_log", new ZapAppleLogBlock(Blocks.STRIPPED_OAK_LOG.getDefaultState(), ZapAppleLogBlock.settings(MapColor.LIGHT_GRAY, MapColor.GRAY)), ItemGroups.BUILDING_BLOCKS);
Block STRIPPED_ZAP_WOOD = register("stripped_zap_wood", new ZapAppleLogBlock(Blocks.STRIPPED_OAK_WOOD, MapColor.GRAY, MapColor.GRAY), ItemGroups.BUILDING_BLOCKS); Block STRIPPED_ZAP_WOOD = register("stripped_zap_wood", new ZapAppleLogBlock(Blocks.STRIPPED_OAK_WOOD.getDefaultState(), ZapAppleLogBlock.settings(MapColor.GRAY, MapColor.GRAY)), ItemGroups.BUILDING_BLOCKS);
Block ZAP_LEAVES = register("zap_leaves", new ZapAppleLeavesBlock(), ItemGroups.NATURAL); Block ZAP_LEAVES = register("zap_leaves", new ZapAppleLeavesBlock(ZapAppleLeavesBlock.settings()), ItemGroups.NATURAL);
Block FLOWERING_ZAP_LEAVES = register("flowering_zap_leaves", new BaseZapAppleLeavesBlock(), ItemGroups.NATURAL); Block FLOWERING_ZAP_LEAVES = register("flowering_zap_leaves", new BaseZapAppleLeavesBlock(BaseZapAppleLeavesBlock.settings()), ItemGroups.NATURAL);
Block ZAP_LEAVES_PLACEHOLDER = register("zap_leaves_placeholder", new ZapAppleLeavesPlaceholderBlock()); Block ZAP_LEAVES_PLACEHOLDER = register("zap_leaves_placeholder", new ZapAppleLeavesPlaceholderBlock(Settings.create().replaceable().noCollision().dropsNothing().air()));
Block ZAP_BULB = register("zap_bulb", new FruitBlock(Settings.create().mapColor(MapColor.GRAY).strength(500, 1200).sounds(BlockSoundGroup.AZALEA_LEAVES), Direction.DOWN, ZAP_LEAVES, FruitBlock.DEFAULT_SHAPE, false)); Block ZAP_BULB = register("zap_bulb", new FruitBlock(Direction.DOWN, ZAP_LEAVES, FruitBlock.DEFAULT_SHAPE, false, Settings.create().mapColor(MapColor.GRAY).strength(500, 1200).sounds(BlockSoundGroup.AZALEA_LEAVES)));
Block ZAP_APPLE = register("zap_apple", new FruitBlock(Settings.create().mapColor(MapColor.GRAY).sounds(BlockSoundGroup.AZALEA_LEAVES), Direction.DOWN, ZAP_LEAVES, FruitBlock.DEFAULT_SHAPE, false)); Block ZAP_APPLE = register("zap_apple", new FruitBlock(Direction.DOWN, ZAP_LEAVES, FruitBlock.DEFAULT_SHAPE, false, Settings.create().mapColor(MapColor.GRAY).sounds(BlockSoundGroup.AZALEA_LEAVES)));
Block PALM_LOG = register("palm_log", BlockConstructionUtils.createLogBlock(MapColor.OFF_WHITE, MapColor.SPRUCE_BROWN), ItemGroups.BUILDING_BLOCKS); Block PALM_LOG = register("palm_log", BlockConstructionUtils.createLogBlock(MapColor.OFF_WHITE, MapColor.SPRUCE_BROWN), ItemGroups.BUILDING_BLOCKS);
Block PALM_WOOD = register("palm_wood", BlockConstructionUtils.createWoodBlock(MapColor.OFF_WHITE), ItemGroups.BUILDING_BLOCKS); Block PALM_WOOD = register("palm_wood", BlockConstructionUtils.createWoodBlock(MapColor.OFF_WHITE), ItemGroups.BUILDING_BLOCKS);
@ -78,69 +78,74 @@ public interface UBlocks {
Block PALM_STAIRS = register("palm_stairs", new StairsBlock(PALM_PLANKS.getDefaultState(), Settings.copy(PALM_PLANKS).pistonBehavior(PistonBehavior.NORMAL)), ItemGroups.BUILDING_BLOCKS); Block PALM_STAIRS = register("palm_stairs", new StairsBlock(PALM_PLANKS.getDefaultState(), Settings.copy(PALM_PLANKS).pistonBehavior(PistonBehavior.NORMAL)), ItemGroups.BUILDING_BLOCKS);
Block PALM_SLAB = register("palm_slab", new SlabBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).strength(2, 3).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.NORMAL)), ItemGroups.BUILDING_BLOCKS); Block PALM_SLAB = register("palm_slab", new SlabBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).strength(2, 3).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.NORMAL)), ItemGroups.BUILDING_BLOCKS);
Block PALM_FENCE = register("palm_fence", new FenceBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).strength(2, 3).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.NORMAL)), ItemGroups.BUILDING_BLOCKS); Block PALM_FENCE = register("palm_fence", new FenceBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).strength(2, 3).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.NORMAL)), ItemGroups.BUILDING_BLOCKS);
Block PALM_FENCE_GATE = register("palm_fence_gate", new FenceGateBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).strength(2, 3).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.NORMAL), WoodType.OAK), ItemGroups.BUILDING_BLOCKS); Block PALM_FENCE_GATE = register("palm_fence_gate", new FenceGateBlock(WoodType.OAK, Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).strength(2, 3).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.NORMAL)), ItemGroups.BUILDING_BLOCKS);
Block PALM_DOOR = register("palm_door", new DoorBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).instrument(Instrument.BASS).strength(3.0f).nonOpaque().burnable().pistonBehavior(PistonBehavior.DESTROY), UWoodTypes.PALM.setType()), ItemGroups.FUNCTIONAL); Block PALM_DOOR = register("palm_door", new DoorBlock(UWoodTypes.PALM.setType(), Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).instrument(Instrument.BASS).strength(3.0f).nonOpaque().burnable().pistonBehavior(PistonBehavior.DESTROY)), ItemGroups.FUNCTIONAL);
Block PALM_TRAPDOOR = register("palm_trapdoor", new TrapdoorBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).instrument(Instrument.BASS).strength(3).nonOpaque().allowsSpawning(BlockConstructionUtils::never).burnable(), UWoodTypes.PALM.setType()), ItemGroups.FUNCTIONAL); Block PALM_TRAPDOOR = register("palm_trapdoor", new TrapdoorBlock(UWoodTypes.PALM.setType(), Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).instrument(Instrument.BASS).strength(3).nonOpaque().allowsSpawning(BlockConstructionUtils::never).burnable()), ItemGroups.FUNCTIONAL);
Block PALM_PRESSURE_PLATE = register("palm_pressure_plate", new PressurePlateBlock(PressurePlateBlock.ActivationRule.EVERYTHING, Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.DESTROY), BlockSetType.OAK), ItemGroups.BUILDING_BLOCKS); Block PALM_PRESSURE_PLATE = register("palm_pressure_plate", new PressurePlateBlock(UWoodTypes.PALM.setType(), Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).noCollision().strength(0.5f).sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.DESTROY)), ItemGroups.BUILDING_BLOCKS);
Block PALM_BUTTON = register("palm_button", BlockConstructionUtils.woodenButton(), ItemGroups.BUILDING_BLOCKS); Block PALM_BUTTON = register("palm_button", BlockConstructionUtils.woodenButton(UWoodTypes.PALM.setType()), ItemGroups.BUILDING_BLOCKS);
Block PALM_SIGN = register("palm_sign", new SignBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).solid().instrument(Instrument.BASS).noCollision().strength(1).burnable().sounds(BlockSoundGroup.WOOD), UWoodTypes.PALM), ItemGroups.FUNCTIONAL); Block PALM_SIGN = register("palm_sign", new SignBlock(UWoodTypes.PALM, Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).solid().instrument(Instrument.BASS).noCollision().strength(1).burnable().sounds(BlockSoundGroup.WOOD)), ItemGroups.FUNCTIONAL);
Block PALM_WALL_SIGN = register("palm_wall_sign", new WallSignBlock(Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).solid().instrument(Instrument.BASS).noCollision().strength(1).dropsLike(PALM_SIGN).burnable(), UWoodTypes.PALM)); Block PALM_WALL_SIGN = register("palm_wall_sign", new WallSignBlock(UWoodTypes.PALM, Settings.create().mapColor(PALM_PLANKS.getDefaultMapColor()).solid().instrument(Instrument.BASS).noCollision().strength(1).dropsLike(PALM_SIGN).burnable()));
Block PALM_HANGING_SIGN = register("palm_hanging_sign", new HangingSignBlock(Settings.create().mapColor(PALM_LOG.getDefaultMapColor()).solid().instrument(Instrument.BASS).noCollision().strength(1).burnable(), UWoodTypes.PALM), ItemGroups.FUNCTIONAL); Block PALM_HANGING_SIGN = register("palm_hanging_sign", new HangingSignBlock(UWoodTypes.PALM, Settings.create().mapColor(PALM_LOG.getDefaultMapColor()).solid().instrument(Instrument.BASS).noCollision().strength(1).burnable()), ItemGroups.FUNCTIONAL);
Block PALM_WALL_HANGING_SIGN = register("palm_wall_hanging_sign", new WallHangingSignBlock(Settings.create().mapColor(PALM_LOG.getDefaultMapColor()).solid().instrument(Instrument.BASS).noCollision().strength(1.0f).burnable().dropsLike(PALM_HANGING_SIGN), UWoodTypes.PALM)); Block PALM_WALL_HANGING_SIGN = register("palm_wall_hanging_sign", new WallHangingSignBlock(UWoodTypes.PALM, Settings.create().mapColor(PALM_LOG.getDefaultMapColor()).solid().instrument(Instrument.BASS).noCollision().strength(1.0f).burnable().dropsLike(PALM_HANGING_SIGN)));
Block PALM_LEAVES = register("palm_leaves", BlockConstructionUtils.createLeavesBlock(BlockSoundGroup.GRASS), ItemGroups.BUILDING_BLOCKS); Block PALM_LEAVES = register("palm_leaves", BlockConstructionUtils.createLeavesBlock(BlockSoundGroup.GRASS), ItemGroups.BUILDING_BLOCKS);
Block BANANAS = register("bananas", new FruitBlock(Settings.create().mapColor(MapColor.YELLOW).sounds(BlockSoundGroup.WOOD).noCollision().ticksRandomly().breakInstantly().pistonBehavior(PistonBehavior.DESTROY), Direction.DOWN, PALM_LEAVES, VoxelShapes.fullCube())); Block BANANAS = register("bananas", new FruitBlock(Direction.DOWN, PALM_LEAVES, VoxelShapes.fullCube(), Settings.create().mapColor(MapColor.YELLOW).sounds(BlockSoundGroup.WOOD).noCollision().ticksRandomly().breakInstantly().pistonBehavior(PistonBehavior.DESTROY)));
PineappleCropBlock PINEAPPLE = register("pineapple", new PineappleCropBlock(Settings.create().sounds(BlockSoundGroup.GRASS).noCollision().breakInstantly().pistonBehavior(PistonBehavior.DESTROY))); PineappleCropBlock PINEAPPLE = register("pineapple", new PineappleCropBlock(Settings.create().sounds(BlockSoundGroup.GRASS).noCollision().breakInstantly().pistonBehavior(PistonBehavior.DESTROY)));
Block MANGO_LEAVES = register("mango_leaves", new FruitBearingBlock(FabricBlockSettings.copy(Blocks.JUNGLE_LEAVES), Block MANGO_LEAVES = register("mango_leaves", new FruitBearingBlock(
0xCCFFAA00, 0xCCFFAA00,
() -> UBlocks.MANGO, () -> UBlocks.MANGO,
() -> UItems.MANGO.getDefaultStack() () -> UItems.MANGO.getDefaultStack(),
FabricBlockSettings.copy(Blocks.JUNGLE_LEAVES)
), ItemGroups.NATURAL); ), ItemGroups.NATURAL);
Block MANGO = register("mango", new FruitBlock(Settings.create().mapColor(MapColor.ORANGE), Direction.DOWN, MANGO_LEAVES, FruitBlock.DEFAULT_SHAPE)); Block MANGO = register("mango", new FruitBlock(Direction.DOWN, MANGO_LEAVES, FruitBlock.DEFAULT_SHAPE, Settings.create().mapColor(MapColor.ORANGE)));
Block WEATHER_VANE = register("weather_vane", new WeatherVaneBlock(Settings.create().mapColor(MapColor.BLACK).requiresTool().strength(3.0f, 6.0f).sounds(BlockSoundGroup.METAL).nonOpaque().pistonBehavior(PistonBehavior.BLOCK)), ItemGroups.TOOLS); Block WEATHER_VANE = register("weather_vane", new WeatherVaneBlock(Settings.create().mapColor(MapColor.BLACK).requiresTool().strength(3.0f, 6.0f).sounds(BlockSoundGroup.METAL).nonOpaque().pistonBehavior(PistonBehavior.BLOCK)), ItemGroups.TOOLS);
Block GREEN_APPLE_LEAVES = register("green_apple_leaves", new FruitBearingBlock(FabricBlockSettings.copy(Blocks.OAK_LEAVES), Block GREEN_APPLE_LEAVES = register("green_apple_leaves", new FruitBearingBlock(
0xE5FFFF88, 0xE5FFFF88,
() -> UBlocks.GREEN_APPLE, () -> UBlocks.GREEN_APPLE,
() -> UItems.GREEN_APPLE.getDefaultStack() () -> UItems.GREEN_APPLE.getDefaultStack(),
FabricBlockSettings.copy(Blocks.OAK_LEAVES)
), ItemGroups.NATURAL); ), ItemGroups.NATURAL);
Block GREEN_APPLE = register("green_apple", new FruitBlock(Settings.create().mapColor(MapColor.GREEN), Direction.DOWN, GREEN_APPLE_LEAVES, FruitBlock.DEFAULT_SHAPE)); Block GREEN_APPLE = register("green_apple", new FruitBlock(Direction.DOWN, GREEN_APPLE_LEAVES, FruitBlock.DEFAULT_SHAPE, Settings.create().mapColor(MapColor.GREEN)));
Block GREEN_APPLE_SPROUT = register("green_apple_sprout", new SproutBlock(0xE5FFFF88, () -> UItems.GREEN_APPLE_SEEDS, () -> UTreeGen.GREEN_APPLE_TREE.sapling().map(Block::getDefaultState).get())); Block GREEN_APPLE_SPROUT = register("green_apple_sprout", new SproutBlock(0xE5FFFF88, () -> UItems.GREEN_APPLE_SEEDS, () -> UTreeGen.GREEN_APPLE_TREE.sapling().map(Block::getDefaultState).get(), SproutBlock.settings()));
Block SWEET_APPLE_LEAVES = register("sweet_apple_leaves", new FruitBearingBlock(FabricBlockSettings.copy(Blocks.OAK_LEAVES), Block SWEET_APPLE_LEAVES = register("sweet_apple_leaves", new FruitBearingBlock(
0xE5FFCC88, 0xE5FFCC88,
() -> UBlocks.SWEET_APPLE, () -> UBlocks.SWEET_APPLE,
() -> UItems.SWEET_APPLE.getDefaultStack() () -> UItems.SWEET_APPLE.getDefaultStack(),
FabricBlockSettings.copy(Blocks.OAK_LEAVES)
), ItemGroups.NATURAL); ), ItemGroups.NATURAL);
Block SWEET_APPLE = register("sweet_apple", new FruitBlock(Settings.create().mapColor(MapColor.GREEN), Direction.DOWN, SWEET_APPLE_LEAVES, FruitBlock.DEFAULT_SHAPE)); Block SWEET_APPLE = register("sweet_apple", new FruitBlock(Direction.DOWN, SWEET_APPLE_LEAVES, FruitBlock.DEFAULT_SHAPE, Settings.create().mapColor(MapColor.GREEN)));
Block SWEET_APPLE_SPROUT = register("sweet_apple_sprout", new SproutBlock(0xE5FFCC88, () -> UItems.SWEET_APPLE_SEEDS, () -> UTreeGen.SWEET_APPLE_TREE.sapling().map(Block::getDefaultState).get())); Block SWEET_APPLE_SPROUT = register("sweet_apple_sprout", new SproutBlock(0xE5FFCC88, () -> UItems.SWEET_APPLE_SEEDS, () -> UTreeGen.SWEET_APPLE_TREE.sapling().map(Block::getDefaultState).get(), SproutBlock.settings()));
Block SOUR_APPLE_LEAVES = register("sour_apple_leaves", new FruitBearingBlock(FabricBlockSettings.copy(Blocks.OAK_LEAVES), Block SOUR_APPLE_LEAVES = register("sour_apple_leaves", new FruitBearingBlock(
0xE5FFCCCC, 0xE5FFCCCC,
() -> UBlocks.SOUR_APPLE, () -> UBlocks.SOUR_APPLE,
() -> UItems.SOUR_APPLE.getDefaultStack() () -> UItems.SOUR_APPLE.getDefaultStack(),
FabricBlockSettings.copy(Blocks.OAK_LEAVES)
), ItemGroups.NATURAL); ), ItemGroups.NATURAL);
Block SOUR_APPLE = register("sour_apple", new FruitBlock(Settings.create().mapColor(MapColor.GREEN), Direction.DOWN, SOUR_APPLE_LEAVES, FruitBlock.DEFAULT_SHAPE)); Block SOUR_APPLE = register("sour_apple", new FruitBlock(Direction.DOWN, SOUR_APPLE_LEAVES, FruitBlock.DEFAULT_SHAPE, Settings.create().mapColor(MapColor.GREEN)));
Block SOUR_APPLE_SPROUT = register("sour_apple_sprout", new SproutBlock(0xE5FFCC88, () -> UItems.SOUR_APPLE_SEEDS, () -> UTreeGen.SOUR_APPLE_TREE.sapling().map(Block::getDefaultState).get())); Block SOUR_APPLE_SPROUT = register("sour_apple_sprout", new SproutBlock(0xE5FFCC88, () -> UItems.SOUR_APPLE_SEEDS, () -> UTreeGen.SOUR_APPLE_TREE.sapling().map(Block::getDefaultState).get(), SproutBlock.settings()));
Block APPLE_PIE = register("apple_pie", new PieBlock(Settings.create().solid().mapColor(MapColor.ORANGE).strength(0.5F).sounds(BlockSoundGroup.WOOL).pistonBehavior(PistonBehavior.DESTROY), Block APPLE_PIE = register("apple_pie", new PieBlock(
() -> UItems.APPLE_PIE_SLICE, () -> UItems.APPLE_PIE_SLICE,
() -> UItems.APPLE_PIE, () -> UItems.APPLE_PIE,
() -> UItems.APPLE_PIE_HOOF () -> UItems.APPLE_PIE_HOOF,
Settings.create().solid().mapColor(MapColor.ORANGE).strength(0.5F).sounds(BlockSoundGroup.WOOL).pistonBehavior(PistonBehavior.DESTROY)
)); ));
SegmentedCropBlock OATS = register("oats", SegmentedCropBlock.create(11, 5, AbstractBlock.Settings.copy(Blocks.WHEAT), () -> UItems.OAT_SEEDS, null, null)); SegmentedCropBlock OATS = register("oats", SegmentedCropBlock.create(11, 5, () -> UItems.OAT_SEEDS, null, null, AbstractBlock.Settings.copy(Blocks.WHEAT)));
SegmentedCropBlock OATS_STEM = register("oats_stem", OATS.createNext(5)); SegmentedCropBlock OATS_STEM = register("oats_stem", OATS.createNext(5));
SegmentedCropBlock OATS_CROWN = register("oats_crown", OATS_STEM.createNext(5)); SegmentedCropBlock OATS_CROWN = register("oats_crown", OATS_STEM.createNext(5));
Block PLUNDER_VINE = register("plunder_vine", new ThornBlock(Settings.create().mapColor(MapColor.DARK_CRIMSON).hardness(1).ticksRandomly().sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.DESTROY), () -> UBlocks.PLUNDER_VINE_BUD)); Block PLUNDER_VINE = register("plunder_vine", new ThornBlock(() -> UBlocks.PLUNDER_VINE_BUD, Settings.create().mapColor(MapColor.DARK_CRIMSON).hardness(1).ticksRandomly().sounds(BlockSoundGroup.WOOD).pistonBehavior(PistonBehavior.DESTROY)));
Block PLUNDER_VINE_BUD = register("plunder_vine_bud", new ThornBudBlock(Settings.create().mapColor(MapColor.DARK_CRIMSON).hardness(1).nonOpaque().ticksRandomly().sounds(BlockSoundGroup.GRASS).pistonBehavior(PistonBehavior.DESTROY), PLUNDER_VINE.getDefaultState())); Block PLUNDER_VINE_BUD = register("plunder_vine_bud", new ThornBudBlock(PLUNDER_VINE.getDefaultState(), Settings.create().mapColor(MapColor.DARK_CRIMSON).hardness(1).nonOpaque().ticksRandomly().sounds(BlockSoundGroup.GRASS).pistonBehavior(PistonBehavior.DESTROY)));
Block CHITIN = register("chitin", new SnowyBlock(Settings.create().mapColor(MapColor.PALE_PURPLE).hardness(5).requiresTool().ticksRandomly().sounds(BlockSoundGroup.CORAL)), ItemGroups.NATURAL); Block CHITIN = register("chitin", new SnowyBlock(Settings.create().mapColor(MapColor.PALE_PURPLE).hardness(5).requiresTool().ticksRandomly().sounds(BlockSoundGroup.CORAL)), ItemGroups.NATURAL);
Block SURFACE_CHITIN = register("surface_chitin", new GrowableBlock(Settings.copy(CHITIN), () -> CHITIN), ItemGroups.NATURAL); Block SURFACE_CHITIN = register("surface_chitin", new GrowableBlock(() -> CHITIN, Settings.copy(CHITIN)), ItemGroups.NATURAL);
Block CHISELLED_CHITIN = register("chiselled_chitin", new Block(Settings.create().mapColor(MapColor.PALE_PURPLE).hardness(5).requiresTool()), ItemGroups.BUILDING_BLOCKS); Block CHISELLED_CHITIN = register("chiselled_chitin", new Block(Settings.create().mapColor(MapColor.PALE_PURPLE).hardness(5).requiresTool()), ItemGroups.BUILDING_BLOCKS);
Block CHITIN_SPIKES = register("chitin_spikes", new SpikesBlock(Settings.copy(CHISELLED_CHITIN).noCollision().nonOpaque()), ItemGroups.NATURAL); Block CHITIN_SPIKES = register("chitin_spikes", new SpikesBlock(Settings.copy(CHISELLED_CHITIN).noCollision().nonOpaque()), ItemGroups.NATURAL);
Block CHISELLED_CHITIN_SLAB = register("chiselled_chitin_slab", new SlabBlock(Settings.copy(CHISELLED_CHITIN)), ItemGroups.BUILDING_BLOCKS); Block CHISELLED_CHITIN_SLAB = register("chiselled_chitin_slab", new SlabBlock(Settings.copy(CHISELLED_CHITIN)), ItemGroups.BUILDING_BLOCKS);
@ -201,9 +206,9 @@ public interface UBlocks {
Block SCALLOP_SHELL = register("scallop_shell", new ShellsBlock(Settings.create().mapColor(MapColor.DULL_PINK).breakInstantly().nonOpaque())); Block SCALLOP_SHELL = register("scallop_shell", new ShellsBlock(Settings.create().mapColor(MapColor.DULL_PINK).breakInstantly().nonOpaque()));
Block TURRET_SHELL = register("turret_shell", new ShellsBlock(Settings.create().mapColor(MapColor.DULL_PINK).breakInstantly().nonOpaque())); Block TURRET_SHELL = register("turret_shell", new ShellsBlock(Settings.create().mapColor(MapColor.DULL_PINK).breakInstantly().nonOpaque()));
Block STABLE_DOOR = register("stable_door", new StableDoorBlock(Settings.copy(Blocks.OAK_DOOR), BlockSetType.OAK), ItemGroups.FUNCTIONAL); Block STABLE_DOOR = register("stable_door", new StableDoorBlock(BlockSetType.OAK, Settings.copy(Blocks.OAK_DOOR)), ItemGroups.FUNCTIONAL);
Block DARK_OAK_DOOR = register("dark_oak_stable_door", new StableDoorBlock(Settings.copy(Blocks.OAK_DOOR), BlockSetType.OAK), ItemGroups.FUNCTIONAL); Block DARK_OAK_DOOR = register("dark_oak_stable_door", new StableDoorBlock(BlockSetType.OAK, Settings.copy(Blocks.OAK_DOOR)), ItemGroups.FUNCTIONAL);
Block CRYSTAL_DOOR = register("crystal_door", new CrystalDoorBlock(Settings.copy(Blocks.IRON_DOOR), UWoodTypes.CRYSTAL), ItemGroups.FUNCTIONAL); Block CRYSTAL_DOOR = register("crystal_door", new CrystalDoorBlock(UWoodTypes.CRYSTAL, Settings.copy(Blocks.IRON_DOOR)), ItemGroups.FUNCTIONAL);
Block CLOUD_DOOR = register("cloud_door", new CloudDoorBlock(Settings.copy(CLOUD), CLOUD.getDefaultState(), UWoodTypes.CLOUD), ItemGroups.FUNCTIONAL); Block CLOUD_DOOR = register("cloud_door", new CloudDoorBlock(Settings.copy(CLOUD), CLOUD.getDefaultState(), UWoodTypes.CLOUD), ItemGroups.FUNCTIONAL);
private static <T extends Block> T register(String name, T item) { private static <T extends Block> T register(String name, T item) {

View file

@ -4,6 +4,7 @@ import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.server.world.WeatherConditions; import com.minelittlepony.unicopia.server.world.WeatherConditions;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.entity.*; import net.minecraft.block.entity.*;
@ -20,6 +21,7 @@ import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
public class WeatherVaneBlock extends BlockWithEntity { public class WeatherVaneBlock extends BlockWithEntity {
public static final MapCodec<WeatherVaneBlock> CODEC = createCodec(WeatherVaneBlock::new);
private static final VoxelShape SHAPE = VoxelShapes.union( private static final VoxelShape SHAPE = VoxelShapes.union(
Block.createCuboidShape(7.5F, 0, 7.5F, 8.5F, 14, 8.5F), Block.createCuboidShape(7.5F, 0, 7.5F, 8.5F, 14, 8.5F),
Block.createCuboidShape(7, 0, 7, 9, 1, 9) Block.createCuboidShape(7, 0, 7, 9, 1, 9)
@ -29,6 +31,11 @@ public class WeatherVaneBlock extends BlockWithEntity {
super(settings); super(settings);
} }
@Override
protected MapCodec<? extends WeatherVaneBlock> getCodec() {
return CODEC;
}
@Deprecated @Deprecated
@Override @Override
public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) { public VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context) {

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.block; package com.minelittlepony.unicopia.block;
import com.minelittlepony.unicopia.server.world.ZapAppleStageStore; import com.minelittlepony.unicopia.server.world.ZapAppleStageStore;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.item.ItemPlacementContext; import net.minecraft.item.ItemPlacementContext;
@ -11,12 +12,19 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
public class ZapAppleLeavesBlock extends BaseZapAppleLeavesBlock { public class ZapAppleLeavesBlock extends BaseZapAppleLeavesBlock {
public static final MapCodec<ZapAppleLeavesBlock> CODEC = createCodec(ZapAppleLeavesBlock::new);
public static final EnumProperty<ZapAppleStageStore.Stage> STAGE = EnumProperty.of("stage", ZapAppleStageStore.Stage.class); public static final EnumProperty<ZapAppleStageStore.Stage> STAGE = EnumProperty.of("stage", ZapAppleStageStore.Stage.class);
ZapAppleLeavesBlock() { ZapAppleLeavesBlock(Settings settings) {
super(settings);
setDefaultState(getDefaultState().with(STAGE, ZapAppleStageStore.Stage.GREENING)); setDefaultState(getDefaultState().with(STAGE, ZapAppleStageStore.Stage.GREENING));
} }
@Override
public MapCodec<? extends ZapAppleLeavesBlock> getCodec() {
return CODEC;
}
@Override @Override
public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean notify) { public void onBlockAdded(BlockState state, World world, BlockPos pos, BlockState oldState, boolean notify) {
if (state.get(PERSISTENT) if (state.get(PERSISTENT)

View file

@ -1,6 +1,7 @@
package com.minelittlepony.unicopia.block; package com.minelittlepony.unicopia.block;
import com.minelittlepony.unicopia.server.world.ZapAppleStageStore; import com.minelittlepony.unicopia.server.world.ZapAppleStageStore;
import com.mojang.serialization.MapCodec;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.server.world.ServerWorld; import net.minecraft.server.world.ServerWorld;
@ -9,9 +10,16 @@ import net.minecraft.util.math.random.Random;
import net.minecraft.world.WorldAccess; import net.minecraft.world.WorldAccess;
public class ZapAppleLeavesPlaceholderBlock extends AirBlock { public class ZapAppleLeavesPlaceholderBlock extends AirBlock {
public static final MapCodec<ZapAppleLeavesPlaceholderBlock> CODEC = createCodec(ZapAppleLeavesPlaceholderBlock::new);
ZapAppleLeavesPlaceholderBlock() { ZapAppleLeavesPlaceholderBlock(Settings settings) {
super(Settings.create().replaceable().noCollision().dropsNothing().air()); super(settings);
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public MapCodec<AirBlock> getCodec() {
return (MapCodec)CODEC;
} }
@Override @Override

View file

@ -1,6 +1,8 @@
package com.minelittlepony.unicopia.block; package com.minelittlepony.unicopia.block;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
import com.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.enums.Instrument; import net.minecraft.block.enums.Instrument;
@ -14,22 +16,34 @@ import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
public class ZapAppleLogBlock extends PillarBlock { public class ZapAppleLogBlock extends PillarBlock {
public static final MapCodec<ZapAppleLogBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
BlockState.CODEC.fieldOf("model_block").forGetter(b -> b.artifialModelBlock),
BedBlock.createSettingsCodec()
).apply(instance, ZapAppleLogBlock::new));
public static final BooleanProperty NATURAL = ZapBlock.NATURAL; public static final BooleanProperty NATURAL = ZapBlock.NATURAL;
private final Block artifialModelBlock; public static Settings settings(MapColor topMapColor, MapColor sideMapColor) {
return Settings.create()
.mapColor(state -> state.get(PillarBlock.AXIS) == Direction.Axis.Y ? topMapColor : sideMapColor)
.instrument(Instrument.BASS)
.strength(2.0f)
.sounds(BlockSoundGroup.WOOD)
.burnable();
}
ZapAppleLogBlock(Block artifialModelBlock, MapColor topMapColor, MapColor sideMapColor) { private final BlockState artifialModelBlock;
super(AbstractBlock.Settings.create().mapColor(
state -> state.get(PillarBlock.AXIS) == Direction.Axis.Y ? topMapColor : sideMapColor ZapAppleLogBlock(BlockState artifialModelBlock, Settings settings) {
) super(settings);
.instrument(Instrument.BASS)
.strength(2.0f)
.sounds(BlockSoundGroup.WOOD)
.burnable());
setDefaultState(getDefaultState().with(NATURAL, true)); setDefaultState(getDefaultState().with(NATURAL, true));
this.artifialModelBlock = artifialModelBlock; this.artifialModelBlock = artifialModelBlock;
} }
@Override
public MapCodec<? extends ZapAppleLogBlock> getCodec() {
return CODEC;
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder); super.appendProperties(builder);
@ -51,7 +65,7 @@ public class ZapAppleLogBlock extends PillarBlock {
@Override @Override
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) { public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
if (!state.get(NATURAL)) { if (!state.get(NATURAL)) {
return artifialModelBlock.calcBlockBreakingDelta(artifialModelBlock.getDefaultState(), player, world, pos); return artifialModelBlock.calcBlockBreakingDelta(player, world, pos);
} }
float delta = super.calcBlockBreakingDelta(state, player, world, pos); float delta = super.calcBlockBreakingDelta(state, player, world, pos);

View file

@ -3,6 +3,9 @@ package com.minelittlepony.unicopia.block;
import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.entity.player.Pony;
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.mojang.serialization.MapCodec;
import com.mojang.serialization.codecs.RecordCodecBuilder;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.LightningEntity; import net.minecraft.entity.LightningEntity;
@ -17,16 +20,27 @@ import net.minecraft.world.World;
import net.minecraft.world.event.GameEvent; import net.minecraft.world.event.GameEvent;
public class ZapBlock extends Block { public class ZapBlock extends Block {
public static final MapCodec<ZapBlock> CODEC = RecordCodecBuilder.mapCodec(instance -> instance.group(
BlockState.CODEC.fieldOf("model_block").forGetter(b -> b.artificialModelBlock),
BedBlock.createSettingsCodec()
).apply(instance, ZapBlock::new));
public static final BooleanProperty NATURAL = BooleanProperty.of("natural"); public static final BooleanProperty NATURAL = BooleanProperty.of("natural");
private final Block artificialModelBlock; private final BlockState artificialModelBlock;
ZapBlock(Settings settings, Block artificialModelBlock) { // unused but we keep it in the event we ever want to return to the zap planks idea
@Deprecated
ZapBlock(BlockState artificialModelBlock, Settings settings) {
super(settings.strength(500, 1200)); super(settings.strength(500, 1200));
setDefaultState(getDefaultState().with(NATURAL, true)); setDefaultState(getDefaultState().with(NATURAL, true));
this.artificialModelBlock = artificialModelBlock; this.artificialModelBlock = artificialModelBlock;
} }
@Override
public MapCodec<? extends ZapBlock> getCodec() {
return CODEC;
}
@Override @Override
protected void appendProperties(StateManager.Builder<Block, BlockState> builder) { protected void appendProperties(StateManager.Builder<Block, BlockState> builder) {
super.appendProperties(builder); super.appendProperties(builder);
@ -48,7 +62,7 @@ public class ZapBlock extends Block {
@Override @Override
public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) { public float calcBlockBreakingDelta(BlockState state, PlayerEntity player, BlockView world, BlockPos pos) {
if (!state.get(NATURAL)) { if (!state.get(NATURAL)) {
return artificialModelBlock.calcBlockBreakingDelta(artificialModelBlock.getDefaultState(), player, world, pos); return artificialModelBlock.calcBlockBreakingDelta(player, world, pos);
} }
float delta = super.calcBlockBreakingDelta(state, player, world, pos); float delta = super.calcBlockBreakingDelta(state, player, world, pos);

View file

@ -45,8 +45,8 @@ public class CloudChestBlock extends ChestBlock implements CloudLike {
@Nullable @Nullable
public ScreenHandler createMenu(int i, PlayerInventory playerInventory, PlayerEntity player) { public ScreenHandler createMenu(int i, PlayerInventory playerInventory, PlayerEntity player) {
if (first.checkUnlocked(player) && second.checkUnlocked(player)) { if (first.checkUnlocked(player) && second.checkUnlocked(player)) {
first.checkLootInteraction(playerInventory.player); first.generateLoot(playerInventory.player);
second.checkLootInteraction(playerInventory.player); second.generateLoot(playerInventory.player);
return GenericContainerScreenHandler.createGeneric9x6(i, playerInventory, inventory); return GenericContainerScreenHandler.createGeneric9x6(i, playerInventory, inventory);
} }
return null; return null;

View file

@ -26,7 +26,7 @@ public class CloudDoorBlock extends DoorBlock implements CloudLike {
private final CloudBlock baseBlock; private final CloudBlock baseBlock;
public CloudDoorBlock(Settings settings, BlockState baseState, BlockSetType blockSet) { public CloudDoorBlock(Settings settings, BlockState baseState, BlockSetType blockSet) {
super(settings, blockSet); super(blockSet, settings);
this.baseState = baseState; this.baseState = baseState;
this.baseBlock = (CloudBlock)baseState.getBlock(); this.baseBlock = (CloudBlock)baseState.getBlock();
} }

View file

@ -29,6 +29,7 @@ import net.minecraft.util.math.Direction;
import net.minecraft.util.shape.VoxelShape; import net.minecraft.util.shape.VoxelShape;
import net.minecraft.world.BlockView; import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldView;
public class CompactedCloudBlock extends CloudBlock { public class CompactedCloudBlock extends CloudBlock {
static final Map<Direction, BooleanProperty> FACING_PROPERTIES = ConnectingBlock.FACING_PROPERTIES; static final Map<Direction, BooleanProperty> FACING_PROPERTIES = ConnectingBlock.FACING_PROPERTIES;
@ -56,7 +57,7 @@ public class CompactedCloudBlock extends CloudBlock {
} }
@Override @Override
public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) { public ItemStack getPickStack(WorldView world, BlockPos pos, BlockState state) {
return baseState.getBlock().getPickStack(world, pos, baseState); return baseState.getBlock().getPickStack(world, pos, baseState);
} }

View file

@ -15,8 +15,8 @@ import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldView;
public class SoggyCloudBlock extends CloudBlock implements Soakable { public class SoggyCloudBlock extends CloudBlock implements Soakable {
@ -35,7 +35,7 @@ public class SoggyCloudBlock extends CloudBlock implements Soakable {
} }
@Override @Override
public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) { public ItemStack getPickStack(WorldView world, BlockPos pos, BlockState state) {
return dryBlock.get().getPickStack(world, pos, state); return dryBlock.get().getPickStack(world, pos, state);
} }

View file

@ -15,8 +15,8 @@ import net.minecraft.util.Hand;
import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.hit.BlockHitResult;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.random.Random; import net.minecraft.util.math.random.Random;
import net.minecraft.world.BlockView;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.WorldView;
public class SoggyCloudSlabBlock extends CloudSlabBlock { public class SoggyCloudSlabBlock extends CloudSlabBlock {
@ -35,7 +35,7 @@ public class SoggyCloudSlabBlock extends CloudSlabBlock {
} }
@Override @Override
public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) { public ItemStack getPickStack(WorldView world, BlockPos pos, BlockState state) {
return dryBlock.get().getPickStack(world, pos, state); return dryBlock.get().getPickStack(world, pos, state);
} }

View file

@ -9,7 +9,7 @@ import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.state.StateManager; import net.minecraft.state.StateManager;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.BlockView; import net.minecraft.world.WorldView;
public class SoggyCloudStairsBlock extends CloudStairsBlock implements Soakable { public class SoggyCloudStairsBlock extends CloudStairsBlock implements Soakable {
@ -28,7 +28,7 @@ public class SoggyCloudStairsBlock extends CloudStairsBlock implements Soakable
} }
@Override @Override
public ItemStack getPickStack(BlockView world, BlockPos pos, BlockState state) { public ItemStack getPickStack(WorldView world, BlockPos pos, BlockState state) {
return dryBlock.get().getPickStack(world, pos, state); return dryBlock.get().getPickStack(world, pos, state);
} }

View file

@ -198,7 +198,8 @@ public class DismissSpellScreen extends GameGui {
tooltip.addAll(FlowingText.wrap(Text.translatable(actualSpell.getType().getTranslationKey() + ".lore").formatted(actualSpell.getAffinity().getColor()), 180).toList()); tooltip.addAll(FlowingText.wrap(Text.translatable(actualSpell.getType().getTranslationKey() + ".lore").formatted(actualSpell.getAffinity().getColor()), 180).toList());
if (spell instanceof TimedSpell timed) { if (spell instanceof TimedSpell timed) {
tooltip.add(ScreenTexts.EMPTY); tooltip.add(ScreenTexts.EMPTY);
tooltip.add(Text.translatable("gui.unicopia.dispell_screen.time_left", StringHelper.formatTicks(timed.getTimer().getTicksRemaining()))); float tickRate = MinecraftClient.getInstance().world.getTickManager().getTickRate();
tooltip.add(Text.translatable("gui.unicopia.dispell_screen.time_left", StringHelper.formatTicks(timed.getTimer().getTicksRemaining(), tickRate)));
} }
tooltip.add(ScreenTexts.EMPTY); tooltip.add(ScreenTexts.EMPTY);
tooltip.add(Text.translatable("gui.unicopia.dispell_screen.discard")); tooltip.add(Text.translatable("gui.unicopia.dispell_screen.discard"));

View file

@ -24,7 +24,7 @@ public class TextBlock extends Label {
} }
@Override @Override
public void render(DrawContext context, int mouseX, int mouseY, float partialTicks) { public void renderWidget(DrawContext context, int mouseX, int mouseY, float partialTicks) {
int textY = (int)(getY() + MinecraftClient.getInstance().textRenderer.fontHeight/1.5F); int textY = (int)(getY() + MinecraftClient.getInstance().textRenderer.fontHeight/1.5F);
for (OrderedText line : getFont().wrapLines(getStyle().getText(), maxWidth)) { for (OrderedText line : getFont().wrapLines(getStyle().getText(), maxWidth)) {

View file

@ -28,7 +28,7 @@ public class TribeButton extends Button {
} }
@Override @Override
public void renderButton(DrawContext context, int mouseX, int mouseY, float partialTicks) { public void renderWidget(DrawContext context, int mouseX, int mouseY, float partialTicks) {
RenderSystem.setShader(GameRenderer::getPositionTexProgram); RenderSystem.setShader(GameRenderer::getPositionTexProgram);
RenderSystem.setShaderColor(1, 1, 1, alpha); RenderSystem.setShaderColor(1, 1, 1, alpha);
RenderSystem.enableBlend(); RenderSystem.enableBlend();

View file

@ -134,7 +134,7 @@ public class IngredientTree implements SpellbookRecipe.CraftingTreeBuilder {
} }
@Override @Override
public void renderButton(DrawContext context, int mouseX, int mouseY, float tickDelta) { public void renderWidget(DrawContext context, int mouseX, int mouseY, float tickDelta) {
RenderSystem.setShaderColor(1, 1, 1, 1); RenderSystem.setShaderColor(1, 1, 1, 1);
RenderSystem.enableBlend(); RenderSystem.enableBlend();

View file

@ -330,7 +330,7 @@ public class SpellbookScreen extends HandledScreen<SpellbookScreenHandler> imple
} }
@Override @Override
public void renderButton(DrawContext context, int mouseX, int mouseY, float tickDelta) { public void renderWidget(DrawContext context, int mouseX, int mouseY, float tickDelta) {
if (!active) { if (!active) {
return; return;
} }
@ -338,7 +338,7 @@ public class SpellbookScreen extends HandledScreen<SpellbookScreenHandler> imple
int state = hovered ? 1 : 0; int state = hovered ? 1 : 0;
sprite.setTextureOffset(23 * state, (int)(479 + 6.5F - (increment * 6.5F))); sprite.setTextureOffset(23 * state, (int)(479 + 6.5F - (increment * 6.5F)));
super.renderButton(context, mouseX, mouseY, tickDelta); super.renderWidget(context, mouseX, mouseY, tickDelta);
} }
} }
@ -353,7 +353,7 @@ public class SpellbookScreen extends HandledScreen<SpellbookScreenHandler> imple
} }
@Override @Override
public void renderButton(DrawContext context, int mouseX, int mouseY, float tickDelta) { public void renderWidget(DrawContext context, int mouseX, int mouseY, float tickDelta) {
RenderSystem.setShader(GameRenderer::getPositionTexProgram); RenderSystem.setShader(GameRenderer::getPositionTexProgram);
RenderSystem.setShaderColor(1, 1, 1, alpha); RenderSystem.setShaderColor(1, 1, 1, alpha);

View file

@ -197,7 +197,7 @@ public class SpellbookTraitDexPageContent implements SpellbookChapterList.Conten
} }
@Override @Override
public void renderButton(DrawContext context, int mouseX, int mouseY, float tickDelta) { public void renderWidget(DrawContext context, int mouseX, int mouseY, float tickDelta) {
TraitDiscovery discoveries = Pony.of(MinecraftClient.getInstance().player).getDiscoveries(); TraitDiscovery discoveries = Pony.of(MinecraftClient.getInstance().player).getDiscoveries();
setEnabled(discoveries.isKnown(trait)); setEnabled(discoveries.isKnown(trait));
@ -213,7 +213,7 @@ public class SpellbookTraitDexPageContent implements SpellbookChapterList.Conten
context.drawTexture(SpellbookScreen.TEXTURE, getX() - 8, getY() - 8, 225, 219, 35, 32, 512, 256); context.drawTexture(SpellbookScreen.TEXTURE, getX() - 8, getY() - 8, 225, 219, 35, 32, 512, 256);
} }
super.renderButton(context, mouseX, mouseY, tickDelta); super.renderWidget(context, mouseX, mouseY, tickDelta);
hovered &= active; hovered &= active;
} }

View file

@ -65,7 +65,7 @@ class BangleGear implements Gear {
@Override @Override
public void pose(PonyModel<?> model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) { public void pose(PonyModel<?> model, Entity entity, boolean rainboom, UUID interpolatorId, float move, float swing, float bodySwing, float ticks) {
alex = entity instanceof ClientPlayerEntity && ((ClientPlayerEntity)entity).method_52814().model() == Model.SLIM; alex = entity instanceof ClientPlayerEntity && ((ClientPlayerEntity)entity).getSkinTextures().model() == Model.SLIM;
FriendshipBraceletItem.getWornBangles((LivingEntity)entity, slot).findFirst().ifPresent(bracelet -> { FriendshipBraceletItem.getWornBangles((LivingEntity)entity, slot).findFirst().ifPresent(bracelet -> {
color = ((DyeableItem)bracelet.getItem()).getColor(bracelet); color = ((DyeableItem)bracelet.getItem()).getColor(bracelet);
glowing = ((GlowableItem)bracelet.getItem()).isGlowing(bracelet); glowing = ((GlowableItem)bracelet.getItem()).isGlowing(bracelet);

View file

@ -60,7 +60,7 @@ public class BraceletFeatureRenderer<E extends LivingEntity> implements Accessor
private void renderBangleThirdPerson(ItemStack item, MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, E entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch, Arm mainArm) { private void renderBangleThirdPerson(ItemStack item, MatrixStack stack, VertexConsumerProvider renderContext, int lightUv, E entity, float limbDistance, float limbAngle, float tickDelta, float age, float headYaw, float headPitch, Arm mainArm) {
int j = ((DyeableItem)item.getItem()).getColor(item); int j = ((DyeableItem)item.getItem()).getColor(item);
boolean alex = entity instanceof ClientPlayerEntity && ((ClientPlayerEntity)entity).method_52814().model() == SkinTextures.Model.SLIM; boolean alex = entity instanceof ClientPlayerEntity && ((ClientPlayerEntity)entity).getSkinTextures().model() == SkinTextures.Model.SLIM;
BraceletModel model = alex ? alexModel : steveModel; BraceletModel model = alex ? alexModel : steveModel;
boolean isLeft = mainArm == Arm.LEFT; boolean isLeft = mainArm == Arm.LEFT;
@ -86,7 +86,7 @@ public class BraceletFeatureRenderer<E extends LivingEntity> implements Accessor
FriendshipBraceletItem.getWornBangles(entity, side == entity.getMainArm() ? TrinketsDelegate.MAINHAND : TrinketsDelegate.OFFHAND).findFirst().ifPresent(item -> { FriendshipBraceletItem.getWornBangles(entity, side == entity.getMainArm() ? TrinketsDelegate.MAINHAND : TrinketsDelegate.OFFHAND).findFirst().ifPresent(item -> {
int j = ((DyeableItem)item.getItem()).getColor(item); int j = ((DyeableItem)item.getItem()).getColor(item);
boolean alex = entity instanceof ClientPlayerEntity && ((ClientPlayerEntity)entity).method_52814().model() == SkinTextures.Model.SLIM; boolean alex = entity instanceof ClientPlayerEntity && ((ClientPlayerEntity)entity).getSkinTextures().model() == SkinTextures.Model.SLIM;
BraceletModel model = alex ? alexModel : steveModel; BraceletModel model = alex ? alexModel : steveModel;

View file

@ -67,7 +67,7 @@ public class ShapingBenchScreenHandler extends StonecutterScreenHandler {
Item item = movingStack.getItem(); Item item = movingStack.getItem();
originalStack = movingStack.copy(); originalStack = movingStack.copy();
if (slot == 1) { if (slot == 1) {
item.onCraft(movingStack, player.getWorld(), player); item.onCraftByPlayer(movingStack, player.getWorld(), player);
if (!insertItem(movingStack, 2, 38, true)) { if (!insertItem(movingStack, 2, 38, true)) {
return ItemStack.EMPTY; return ItemStack.EMPTY;
} }

View file

@ -90,6 +90,7 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab
int tabY, int tabY,
int color, int color,
List<Page> pages) { List<Page> pages) {
@Deprecated
public Chapter(Identifier id, JsonObject json) { public Chapter(Identifier id, JsonObject json) {
this(id, this(id,
TabSide.valueOf(JsonHelper.getString(json, "side")), TabSide.valueOf(JsonHelper.getString(json, "side")),
@ -99,6 +100,7 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab
); );
} }
@Deprecated
private static List<Page> loadContent(JsonObject json) { private static List<Page> loadContent(JsonObject json) {
return Optional.of(JsonHelper.getArray(json, "pages", new JsonArray())) return Optional.of(JsonHelper.getArray(json, "pages", new JsonArray()))
.filter(pages -> pages.size() > 0) .filter(pages -> pages.size() > 0)
@ -123,13 +125,15 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab
int level, int level,
List<Element> elements List<Element> elements
) { ) {
@Deprecated
public Page(JsonElement json) { public Page(JsonElement json) {
this(json.getAsJsonObject()); this(json.getAsJsonObject());
} }
@Deprecated
public Page(JsonObject json) { public Page(JsonObject json) {
this( this(
Text.Serializer.fromJson(json.get("title")), Text.Serialization.fromJsonTree(json.get("title")),
JsonHelper.getInt(json, "level", 0), JsonHelper.getInt(json, "level", 0),
new ArrayList<>() new ArrayList<>()
); );
@ -200,6 +204,7 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab
} }
record Ingredients(List<Element> entries) implements Element { record Ingredients(List<Element> entries) implements Element {
@Deprecated
static Element loadIngredient(JsonObject json) { static Element loadIngredient(JsonObject json) {
int count = JsonHelper.getInt(json, "count", 1); int count = JsonHelper.getInt(json, "count", 1);
if (json.has("item")) { if (json.has("item")) {
@ -214,7 +219,7 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab
return new Multi(count, new Id((byte)4, Identifier.tryParse(json.get("spell").getAsString()))); return new Multi(count, new Id((byte)4, Identifier.tryParse(json.get("spell").getAsString())));
} }
return new Multi(count, new TextBlock(Text.Serializer.fromJson(json.get("text")))); return new Multi(count, new TextBlock(Text.Serialization.fromJsonTree(json.get("text"))));
} }
@Override @Override
@ -258,7 +263,7 @@ public class SpellbookChapterLoader extends JsonDataLoader implements Identifiab
} }
} }
return new TextBlock(Text.Serializer.fromJson(json)); return new TextBlock(Text.Serialization.fromJsonTree(json));
} }
private static Bounds boundsFromJson(JsonObject el) { private static Bounds boundsFromJson(JsonObject el) {

View file

@ -3,6 +3,7 @@ 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;
import net.minecraft.client.MinecraftClient;
import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.attribute.EntityAttributes;
import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffectInstance;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
@ -68,7 +69,8 @@ record StatusEffectAffliction(Identifier effect, Range seconds, Range amplifier,
text = Text.translatable("potion.withAmplifier", text, Text.translatable("potion.potency." + (amplifier.min()))); text = Text.translatable("potion.withAmplifier", text, Text.translatable("potion.potency." + (amplifier.min())));
} }
text = Text.translatable("potion.withDuration", text, StringHelper.formatTicks(seconds.min() * 20)); float tickRate = MinecraftClient.getInstance().world.getTickManager().getTickRate();
text = Text.translatable("potion.withDuration", text, StringHelper.formatTicks(seconds.min() * 20, tickRate));
if (chance > 0) { if (chance > 0) {
text = Text.translatable("potion.withChance", chance, text); text = Text.translatable("potion.withChance", chance, text);

View file

@ -41,6 +41,7 @@ import net.minecraft.util.Hand;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameRules; import net.minecraft.world.GameRules;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.explosion.Explosion;
public class SpellbookEntity extends MobEntity implements MagicImmune { public class SpellbookEntity extends MobEntity implements MagicImmune {
private static final TrackedData<Byte> LOCKED = DataTracker.registerData(SpellbookEntity.class, TrackedDataHandlerRegistry.BYTE); private static final TrackedData<Byte> LOCKED = DataTracker.registerData(SpellbookEntity.class, TrackedDataHandlerRegistry.BYTE);
@ -304,7 +305,7 @@ public class SpellbookEntity extends MobEntity implements MagicImmune {
} }
@Override @Override
public boolean isImmuneToExplosion() { public boolean isImmuneToExplosion(Explosion explosion) {
return true; return true;
} }

View file

@ -4,6 +4,7 @@ import java.util.function.Predicate;
import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.entity.behaviour.EntityBehaviour; import com.minelittlepony.unicopia.entity.behaviour.EntityBehaviour;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.PhysicsBodyProjectileEntity; import com.minelittlepony.unicopia.projectile.PhysicsBodyProjectileEntity;
@ -28,7 +29,7 @@ public interface UEntities {
.trackRangeBlocks(100) .trackRangeBlocks(100)
.trackedUpdateRate(2) .trackedUpdateRate(2)
.dimensions(EntityDimensions.fixed(0.25F, 0.25F))); .dimensions(EntityDimensions.fixed(0.25F, 0.25F)));
EntityType<PhysicsBodyProjectileEntity> MUFFIN = register("muffin", FabricEntityTypeBuilder.<PhysicsBodyProjectileEntity>create(SpawnGroup.MISC, PhysicsBodyProjectileEntity::new) EntityType<PhysicsBodyProjectileEntity> MUFFIN = register("muffin", FabricEntityTypeBuilder.<PhysicsBodyProjectileEntity>create(SpawnGroup.MISC, (type, world) -> new PhysicsBodyProjectileEntity(type, world, UItems.MUFFIN.getDefaultStack()))
.trackRangeBlocks(100) .trackRangeBlocks(100)
.trackedUpdateRate(2) .trackedUpdateRate(2)
.dimensions(EntityDimensions.fixed(0.25F, 0.25F))); .dimensions(EntityDimensions.fixed(0.25F, 0.25F)));

View file

@ -36,12 +36,13 @@ public class HeavyProjectileItem extends ProjectileItem {
@Override @Override
protected PhysicsBodyProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) { protected PhysicsBodyProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) {
PhysicsBodyProjectileEntity projectile = player == null ? new PhysicsBodyProjectileEntity(world) : new PhysicsBodyProjectileEntity(world, player); PhysicsBodyProjectileEntity projectile = player == null
? new PhysicsBodyProjectileEntity(world, stack.copyWithCount(1))
: new PhysicsBodyProjectileEntity(world, player, stack.copyWithCount(1));
if (player != null) { if (player != null) {
projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1); projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1);
} }
projectile.pickupType = PersistentProjectileEntity.PickupPermission.ALLOWED; projectile.pickupType = PersistentProjectileEntity.PickupPermission.ALLOWED;
projectile.setStack(stack.copy().split(1));
return projectile; return projectile;
} }

View file

@ -13,7 +13,6 @@ import net.minecraft.recipe.CuttingRecipe;
import net.minecraft.recipe.Ingredient; import net.minecraft.recipe.Ingredient;
import net.minecraft.recipe.RecipeSerializer; import net.minecraft.recipe.RecipeSerializer;
import net.minecraft.recipe.RecipeType; import net.minecraft.recipe.RecipeType;
import net.minecraft.recipe.ShapedRecipe;
import net.minecraft.recipe.SpecialRecipeSerializer; import net.minecraft.recipe.SpecialRecipeSerializer;
import net.minecraft.recipe.StonecuttingRecipe; import net.minecraft.recipe.StonecuttingRecipe;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
@ -38,7 +37,7 @@ public interface URecipes {
RecipeSerializer<GlowingRecipe> GLOWING_SERIALIZER = RecipeSerializer.register("unicopia:crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new)); RecipeSerializer<GlowingRecipe> GLOWING_SERIALIZER = RecipeSerializer.register("unicopia:crafting_glowing", new SpecialRecipeSerializer<>(GlowingRecipe::new));
RecipeSerializer<JarInsertRecipe> JAR_INSERT_SERIALIZER = RecipeSerializer.register("unicopia:jar_insert", new SpecialRecipeSerializer<>(JarInsertRecipe::new)); RecipeSerializer<JarInsertRecipe> JAR_INSERT_SERIALIZER = RecipeSerializer.register("unicopia:jar_insert", new SpecialRecipeSerializer<>(JarInsertRecipe::new));
RecipeSerializer<JarExtractRecipe> JAR_EXTRACT_SERIALIZER = RecipeSerializer.register("unicopia:jar_extract", new SpecialRecipeSerializer<>(JarExtractRecipe::new)); RecipeSerializer<JarExtractRecipe> JAR_EXTRACT_SERIALIZER = RecipeSerializer.register("unicopia:jar_extract", new SpecialRecipeSerializer<>(JarExtractRecipe::new));
RecipeSerializer<ShapedRecipe> CRAFTING_MAGICAL_SERIALIZER = RecipeSerializer.register("unicopia:crafting_magical", new SpellShapedCraftingRecipe.Serializer()); RecipeSerializer<SpellShapedCraftingRecipe> CRAFTING_MAGICAL_SERIALIZER = RecipeSerializer.register("unicopia:crafting_magical", new SpellShapedCraftingRecipe.Serializer());
RecipeSerializer<SpellCraftingRecipe> TRAIT_REQUIREMENT = RecipeSerializer.register("unicopia:spellbook/crafting", new SpellCraftingRecipe.Serializer()); RecipeSerializer<SpellCraftingRecipe> TRAIT_REQUIREMENT = RecipeSerializer.register("unicopia:spellbook/crafting", new SpellCraftingRecipe.Serializer());
RecipeSerializer<SpellEnhancingRecipe> TRAIT_COMBINING = RecipeSerializer.register("unicopia:spellbook/combining", new SpellEnhancingRecipe.Serializer()); RecipeSerializer<SpellEnhancingRecipe> TRAIT_COMBINING = RecipeSerializer.register("unicopia:spellbook/combining", new SpellEnhancingRecipe.Serializer());
RecipeSerializer<SpellDuplicatingRecipe> SPELL_DUPLICATING = RecipeSerializer.register("unicopia:spellbook/duplicating", new SpellDuplicatingRecipe.Serializer()); RecipeSerializer<SpellDuplicatingRecipe> SPELL_DUPLICATING = RecipeSerializer.register("unicopia:spellbook/duplicating", new SpellDuplicatingRecipe.Serializer());

View file

@ -15,6 +15,7 @@ import net.minecraft.network.PacketByteBuf;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtIo; import net.minecraft.nbt.NbtIo;
import net.minecraft.nbt.NbtTagSizeTracker;
/** /**
* Sent to the client to update various data pertaining to a particular player. * Sent to the client to update various data pertaining to a particular player.
@ -30,7 +31,7 @@ public class MsgPlayerCapabilities implements HandledPacket<PlayerEntity> {
MsgPlayerCapabilities(PacketByteBuf buffer) { MsgPlayerCapabilities(PacketByteBuf buffer) {
playerId = buffer.readUuid(); playerId = buffer.readUuid();
try (InputStream in = new ByteBufInputStream(buffer)) { try (InputStream in = new ByteBufInputStream(buffer)) {
compoundTag = NbtIo.readCompressed(in); compoundTag = NbtIo.readCompressed(in, NbtTagSizeTracker.ofUnlimitedBytes());
} catch (IOException e) { } catch (IOException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
} }

View file

@ -46,16 +46,16 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl
private int inWaterTime; private int inWaterTime;
public PhysicsBodyProjectileEntity(EntityType<PhysicsBodyProjectileEntity> type, World world) { public PhysicsBodyProjectileEntity(EntityType<PhysicsBodyProjectileEntity> type, World world, ItemStack stack) {
super(type, world); super(type, world, stack);
} }
public PhysicsBodyProjectileEntity(World world) { public PhysicsBodyProjectileEntity(World world, ItemStack stack) {
this(UEntities.MUFFIN, world); this(UEntities.MUFFIN, world, stack);
} }
public PhysicsBodyProjectileEntity(World world, @Nullable LivingEntity thrower) { public PhysicsBodyProjectileEntity(World world, @Nullable LivingEntity thrower, ItemStack stack) {
super(UEntities.MUFFIN, thrower, world); super(UEntities.MUFFIN, thrower, world, stack);
} }
@Override @Override

View file

@ -11,10 +11,8 @@ import net.fabricmc.fabric.api.biome.v1.*;
import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback; import net.fabricmc.fabric.api.event.registry.DynamicRegistrySetupCallback;
import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings; import net.fabricmc.fabric.api.object.builder.v1.block.FabricBlockSettings;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.sapling.SaplingGenerator;
import net.minecraft.item.*; import net.minecraft.item.*;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.random.Random;
import net.minecraft.registry.*; import net.minecraft.registry.*;
import net.minecraft.registry.tag.BiomeTags; import net.minecraft.registry.tag.BiomeTags;
import net.minecraft.world.gen.GenerationStep; import net.minecraft.world.gen.GenerationStep;
@ -136,12 +134,7 @@ public record Tree (
RegistryKey<PlacedFeature> i = RegistryKey.of(RegistryKeys.PLACED_FEATURE, id); RegistryKey<PlacedFeature> i = RegistryKey.of(RegistryKeys.PLACED_FEATURE, id);
BiomeModifications.addFeature(selector, GenerationStep.Feature.VEGETAL_DECORATION, i); BiomeModifications.addFeature(selector, GenerationStep.Feature.VEGETAL_DECORATION, i);
return i; return i;
}), saplingId.map(id -> UBlocks.register(id, saplingConstructor.apply(new SaplingGenerator() { }), saplingId.map(id -> UBlocks.register(id, saplingConstructor.apply(new SaplingGenerator("dark_oak", Optional.of(configuredFeatureId), Optional.empty(), Optional.empty()), FabricBlockSettings.copy(Blocks.OAK_SAPLING)), ItemGroups.NATURAL)), countModifier);
@Override
protected RegistryKey<ConfiguredFeature<?, ?>> getTreeFeature(Random rng, boolean flowersNearby) {
return configuredFeatureId;
}
}, FabricBlockSettings.copy(Blocks.OAK_SAPLING)), ItemGroups.NATURAL)), countModifier);
if (REGISTRY.isEmpty()) { if (REGISTRY.isEmpty()) {
bootstrap(); bootstrap();

View file

@ -1,7 +1,12 @@
package com.minelittlepony.unicopia.util; package com.minelittlepony.unicopia.util;
import java.util.ArrayList;
import java.util.Optional; import java.util.Optional;
import java.util.Set;
import java.util.function.Supplier;
import java.util.stream.Collectors;
import com.mojang.datafixers.util.Either;
import com.mojang.datafixers.util.Pair; import com.mojang.datafixers.util.Pair;
import com.mojang.serialization.Codec; import com.mojang.serialization.Codec;
import com.mojang.serialization.DataResult; import com.mojang.serialization.DataResult;
@ -10,7 +15,13 @@ import com.mojang.serialization.DynamicOps;
import com.mojang.serialization.Encoder; import com.mojang.serialization.Encoder;
import com.mojang.serialization.MapCodec; import com.mojang.serialization.MapCodec;
import net.fabricmc.fabric.api.util.TriState;
import net.minecraft.item.ItemConvertible;
import net.minecraft.registry.Registries;
import net.minecraft.util.dynamic.Codecs;
public interface CodecUtils { public interface CodecUtils {
Codec<ItemConvertible> ITEM = Registries.ITEM.getCodec().xmap(i -> () -> i, ItemConvertible::asItem);
/** /**
* Combines the result of two unrelated codecs into a single object. * Combines the result of two unrelated codecs into a single object.
* <p> * <p>
@ -58,4 +69,24 @@ public interface CodecUtils {
} }
}); });
} }
static <K> Codec<K> xor(Codec<K> left, Codec<K> right) {
return Codecs.xor(left, right).xmap(either -> either.left().or(either::right).get(), Either::left);
}
static <K> Codec<Set<K>> setOf(Codec<K> codec) {
return codec.listOf().xmap(
l -> l.stream().distinct().collect(Collectors.toUnmodifiableSet()),
s -> new ArrayList<>(s)
);
}
static <K> Codec<Supplier<K>> supplierOf(Codec<K> codec) {
return codec.xmap(k -> () -> k, Supplier::get);
}
static MapCodec<TriState> tristateOf(String fieldName) {
return Codec.BOOL.optionalFieldOf(fieldName)
.<TriState>xmap(b -> b.map(TriState::of).orElse(TriState.DEFAULT), t -> Optional.ofNullable(t.get()));
}
} }