Merge branch '1.20.2' into 1.20.4

This commit is contained in:
Sollace 2024-03-02 15:48:20 +00:00
commit 67caa81a07
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
84 changed files with 747 additions and 64 deletions

1
BlockusAddon Submodule

@ -0,0 +1 @@
Subproject commit 94ff5babb976911f46d7efcdad2586652fb33047

View file

@ -11,6 +11,8 @@ import com.minelittlepony.unicopia.item.enchantment.WantItNeedItEnchantment;
import net.minecraft.entity.*; import net.minecraft.entity.*;
import net.minecraft.entity.decoration.AbstractDecorationEntity; import net.minecraft.entity.decoration.AbstractDecorationEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.ProjectileEntity;
import net.minecraft.entity.vehicle.BoatEntity;
import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.predicate.entity.EntityPredicates;
public interface EquinePredicates { public interface EquinePredicates {
@ -33,7 +35,11 @@ public interface EquinePredicates {
Predicate<Entity> IS_CASTER = e -> !e.isRemoved() && (e instanceof Caster || IS_PLAYER.test(e)); Predicate<Entity> IS_CASTER = e -> !e.isRemoved() && (e instanceof Caster || IS_PLAYER.test(e));
Predicate<Entity> IS_PLACED_SPELL = e -> e instanceof Caster && !e.isRemoved(); Predicate<Entity> IS_PLACED_SPELL = e -> e instanceof Caster && !e.isRemoved();
Predicate<Entity> IS_MAGIC_IMMUNE = e -> (e instanceof MagicImmune || !(e instanceof LivingEntity)) && !(e instanceof ItemEntity) && !(e instanceof ExperienceOrbEntity); Predicate<Entity> IS_MAGIC_IMMUNE = e -> (e instanceof MagicImmune || !(e instanceof LivingEntity))
&& !(e instanceof ItemEntity)
&& !(e instanceof ExperienceOrbEntity)
&& !(e instanceof BoatEntity)
&& !(e instanceof ProjectileEntity);
Predicate<Entity> EXCEPT_MAGIC_IMMUNE = IS_MAGIC_IMMUNE.negate(); Predicate<Entity> EXCEPT_MAGIC_IMMUNE = IS_MAGIC_IMMUNE.negate();
Predicate<Entity> VALID_LIVING_AND_NOT_MAGIC_IMMUNE = EntityPredicates.VALID_LIVING_ENTITY.and(EXCEPT_MAGIC_IMMUNE); Predicate<Entity> VALID_LIVING_AND_NOT_MAGIC_IMMUNE = EntityPredicates.VALID_LIVING_ENTITY.and(EXCEPT_MAGIC_IMMUNE);

View file

@ -113,7 +113,7 @@ public class UnicornCastingAbility extends AbstractSpellCastingAbility {
} else { } else {
player.setAnimation(Animation.ARMS_UP, Animation.Recipient.HUMAN); player.setAnimation(Animation.ARMS_UP, Animation.Recipient.HUMAN);
if (s instanceof HomingSpell homer) { if (s instanceof HomingSpell homer) {
TraceHelper.findEntity(player.asEntity(), homer.getRange(player), 1, EquinePredicates.VALID_LIVING_AND_NOT_MAGIC_IMMUNE).ifPresent(homer::setTarget); TraceHelper.findEntity(player.asEntity(), homer.getRange(player), 1, EquinePredicates.EXCEPT_MAGIC_IMMUNE).ifPresent(homer::setTarget);
} }
player.playSound(USounds.SPELL_CAST_SUCCESS, 0.05F, 2.2F); player.playSound(USounds.SPELL_CAST_SUCCESS, 0.05F, 2.2F);
} }

View file

@ -30,6 +30,7 @@ public class ChillingBreathSpell extends AbstractSpell implements HomingSpell {
public boolean setTarget(Entity target) { public boolean setTarget(Entity target) {
if (target instanceof LavaAffine affine) { if (target instanceof LavaAffine affine) {
affine.setLavaAffine(!affine.isLavaAffine()); affine.setLavaAffine(!affine.isLavaAffine());
setDead();
} }
return true; return true;
} }

View file

@ -122,7 +122,7 @@ public class SlimePustuleBlock extends Block {
@Override @Override
public BlockState 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(player.canHarvest(state) ? player : null, new Box(pos).expand(1)).forEach(entity -> {
entity.damage(entity.getDamageSources().inFire(), 2); entity.damage(entity.getDamageSources().inFire(), 2);
entity.setFireTicks(3); entity.setFireTicks(3);
}); });

View file

@ -26,7 +26,9 @@ import com.minelittlepony.unicopia.client.render.*;
import com.minelittlepony.unicopia.client.render.entity.*; import com.minelittlepony.unicopia.client.render.entity.*;
import com.minelittlepony.unicopia.client.render.shader.UShaders; import com.minelittlepony.unicopia.client.render.shader.UShaders;
import com.minelittlepony.unicopia.client.render.spell.SpellRendererFactory; import com.minelittlepony.unicopia.client.render.spell.SpellRendererFactory;
import com.minelittlepony.unicopia.entity.mob.ButterflyEntity;
import com.minelittlepony.unicopia.entity.mob.UEntities; import com.minelittlepony.unicopia.entity.mob.UEntities;
import com.minelittlepony.unicopia.item.ButterflyItem;
import com.minelittlepony.unicopia.item.ChameleonItem; import com.minelittlepony.unicopia.item.ChameleonItem;
import com.minelittlepony.unicopia.item.EnchantableItem; import com.minelittlepony.unicopia.item.EnchantableItem;
import com.minelittlepony.unicopia.item.FancyBedItem; import com.minelittlepony.unicopia.item.FancyBedItem;
@ -119,6 +121,7 @@ public interface URenderers {
PolearmRenderer.register(UItems.WOODEN_POLEARM, UItems.STONE_POLEARM, UItems.IRON_POLEARM, UItems.GOLDEN_POLEARM, UItems.DIAMOND_POLEARM, UItems.NETHERITE_POLEARM); PolearmRenderer.register(UItems.WOODEN_POLEARM, UItems.STONE_POLEARM, UItems.IRON_POLEARM, UItems.GOLDEN_POLEARM, UItems.DIAMOND_POLEARM, UItems.NETHERITE_POLEARM);
ModelPredicateProviderRegistry.register(UItems.GEMSTONE, new Identifier("affinity"), (stack, world, entity, seed) -> EnchantableItem.isEnchanted(stack) ? EnchantableItem.getSpellKey(stack).getAffinity().getAlignment() : 0); ModelPredicateProviderRegistry.register(UItems.GEMSTONE, new Identifier("affinity"), (stack, world, entity, seed) -> EnchantableItem.isEnchanted(stack) ? EnchantableItem.getSpellKey(stack).getAffinity().getAlignment() : 0);
ModelPredicateProviderRegistry.register(UItems.ROCK_CANDY, new Identifier("count"), (stack, world, entity, seed) -> stack.getCount() / (float)stack.getMaxCount()); ModelPredicateProviderRegistry.register(UItems.ROCK_CANDY, new Identifier("count"), (stack, world, entity, seed) -> stack.getCount() / (float)stack.getMaxCount());
ModelPredicateProviderRegistry.register(UItems.BUTTERFLY, new Identifier("variant"), (stack, world, entity, seed) -> (float)ButterflyItem.getVariant(stack).ordinal() / ButterflyEntity.Variant.VALUES.length);
ModelPredicateProviderRegistry.register(Unicopia.id("zap_cycle"), new ClampedModelPredicateProvider() { ModelPredicateProviderRegistry.register(Unicopia.id("zap_cycle"), new ClampedModelPredicateProvider() {
private double targetAngle; private double targetAngle;
private double lastAngle; private double lastAngle;

View file

@ -34,7 +34,7 @@ class EntityDisguiseRenderer {
public boolean render(Living<?> pony, Disguise disguise, public boolean render(Living<?> pony, Disguise disguise,
double x, double y, double z, double x, double y, double z,
float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light) { float tickDelta, MatrixStack matrices, VertexConsumerProvider vertices, int light) {
int fireTicks = pony.asEntity().doesRenderOnFire() ? 1 : 0; int fireTicks = pony.asEntity().doesRenderOnFire() ? 1 : 0;
disguise.update(pony, false); disguise.update(pony, false);
@ -51,20 +51,20 @@ class EntityDisguiseRenderer {
e.setBoundingBox(pony.asEntity().getBoundingBox()); e.setBoundingBox(pony.asEntity().getBoundingBox());
} }
render(ve, e, x, y, z, fireTicks, tickDelta, matrices, vertexConsumers, light); render(ve, e, x, y, z, fireTicks, tickDelta, matrices, vertices, light);
ve.getAttachments().forEach(ee -> { ve.getAttachments().forEach(ee -> {
PehkUtil.copyScale(pony.asEntity(), ee); PehkUtil.copyScale(pony.asEntity(), ee);
Vec3d difference = ee.getPos().subtract(e.getPos()); Vec3d difference = ee.getPos().subtract(e.getPos());
render(ve, ee, x + difference.x, y + difference.y, z + difference.z, fireTicks, tickDelta, matrices, vertexConsumers, light); render(ve, ee, x + difference.x, y + difference.y, z + difference.z, fireTicks, tickDelta, matrices, vertices, light);
PehkUtil.clearScale(ee); PehkUtil.clearScale(ee);
}); });
matrices.push(); matrices.push();
matrices.translate(x, y, z); matrices.translate(x, y, z);
SpellEffectsRenderDispatcher.INSTANCE.render(matrices, vertexConsumers, light, pony, 0, 0, tickDelta, pony.asEntity().age + tickDelta, 0, 0); SpellEffectsRenderDispatcher.INSTANCE.render(matrices, vertices, light, pony, 0, 0, tickDelta, pony.asEntity().age + tickDelta, 0, 0);
matrices.pop(); matrices.pop();
delegate.afterEntityRender(pony, matrices, light); delegate.afterEntityRender(pony, matrices, vertices, light);
PehkUtil.clearScale(e); PehkUtil.clearScale(e);
return true; return true;
} }

View file

@ -31,6 +31,7 @@ import net.minecraft.util.math.*;
public class WorldRenderDelegate { public class WorldRenderDelegate {
public static final WorldRenderDelegate INSTANCE = new WorldRenderDelegate(); public static final WorldRenderDelegate INSTANCE = new WorldRenderDelegate();
private static final Optional<Vec3d> RED_SKY_COLOR = Optional.of(new Vec3d(1, 0, 0)); private static final Optional<Vec3d> RED_SKY_COLOR = Optional.of(new Vec3d(1, 0, 0));
private static final Identifier SHADOW_TEXTURE = new Identifier("textures/misc/shadow.png");
private final EntityReplacementManager disguiseLookup = new EntityReplacementManager(); private final EntityReplacementManager disguiseLookup = new EntityReplacementManager();
private final EntityDisguiseRenderer disguiseRenderer = new EntityDisguiseRenderer(this); private final EntityDisguiseRenderer disguiseRenderer = new EntityDisguiseRenderer(this);
@ -71,13 +72,23 @@ public class WorldRenderDelegate {
if (MinecraftClient.getInstance().getResourceManager().getResource(frostingTexture).isPresent()) { if (MinecraftClient.getInstance().getResourceManager().getResource(frostingTexture).isPresent()) {
recurseFrosting = true; recurseFrosting = true;
Immediate immediate = MinecraftClient.getInstance().getBufferBuilders().getEffectVertexConsumers();
client.getEntityRenderDispatcher().render(entity, x, y, z, yaw, tickDelta, matrices, layer -> { client.getEntityRenderDispatcher().render(entity, x, y, z, yaw, tickDelta, matrices, layer -> {
if (RenderLayerUtil.getTexture(layer).orElse(null) == null) {
Identifier texture = RenderLayerUtil.getTexture(layer).orElse(null);
if (texture == null || texture.equals(SHADOW_TEXTURE)) {
return vertices.getBuffer(layer); return vertices.getBuffer(layer);
} }
return VertexConsumers.union(vertices.getBuffer(layer), vertices.getBuffer(RenderLayers.getEntityTranslucent(frostingTexture))); return VertexConsumers.union(
vertices.getBuffer(layer),
immediate.getBuffer(RenderLayers.getEntityTranslucent(frostingTexture))
);
}, light); }, light);
recurseFrosting = false; recurseFrosting = false;
immediate.draw();
return true; return true;
} }
} }
@ -89,14 +100,13 @@ public class WorldRenderDelegate {
return Equine.of(entity).filter(eq -> onEntityRender(eq, x, y, z, yaw, tickDelta, matrices, vertices, light)).isPresent(); return Equine.of(entity).filter(eq -> onEntityRender(eq, x, y, z, yaw, tickDelta, matrices, vertices, light)).isPresent();
} }
public void afterEntityRender(Equine<?> pony, MatrixStack matrices, int light) { public void afterEntityRender(Equine<?> pony, MatrixStack matrices, VertexConsumerProvider vertices, int light) {
if (recurseFrosting) { if (recurseFrosting) {
return; return;
} }
if (pony instanceof Creature creature && smittenEyesRenderer.isSmitten(creature)) { if (pony instanceof Creature creature && smittenEyesRenderer.isSmitten(creature)) {
Immediate immediate = MinecraftClient.getInstance().getBufferBuilders().getEntityVertexConsumers(); smittenEyesRenderer.render(creature, matrices, vertices, light, 0);
smittenEyesRenderer.render(creature, matrices, immediate, light, 0);
} }
if (pony instanceof Pony p) { if (pony instanceof Pony p) {

View file

@ -79,6 +79,10 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
} }
public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, Caster<?> caster, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) { public void render(MatrixStack matrices, VertexConsumerProvider vertices, int light, Caster<?> caster, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
if (!((RenderDispatcherAccessor)client.getEntityRenderDispatcher()).shouldRenderShadows()) {
return;
}
caster.getSpellSlot().forEach(spell -> { caster.getSpellSlot().forEach(spell -> {
render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch); render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
return Operation.SKIP; return Operation.SKIP;
@ -156,4 +160,8 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
matrices.pop(); matrices.pop();
} }
} }
public interface RenderDispatcherAccessor {
boolean shouldRenderShadows();
}
} }

View file

@ -70,13 +70,17 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
public Creature(LivingEntity entity) { public Creature(LivingEntity entity) {
super(entity, EFFECT); super(entity, EFFECT);
physics = new EntityPhysics<>(entity, GRAVITY); physics = new EntityPhysics<>(entity, GRAVITY);
addTicker(physics);
addTicker(this::updateConsumption);
}
@Override
public void initDataTracker() {
super.initDataTracker();
entity.getDataTracker().startTracking(MASTER, owner.toNBT()); entity.getDataTracker().startTracking(MASTER, owner.toNBT());
entity.getDataTracker().startTracking(EATING, 0); entity.getDataTracker().startTracking(EATING, 0);
entity.getDataTracker().startTracking(DISCORDED, false); entity.getDataTracker().startTracking(DISCORDED, false);
entity.getDataTracker().startTracking(SMITTEN, false); entity.getDataTracker().startTracking(SMITTEN, false);
addTicker(physics);
addTicker(this::updateConsumption);
} }
@Override @Override

View file

@ -28,16 +28,8 @@ public class EntityPhysics<T extends Entity> implements Physics, Copyable<Entity
private float lastGravity = 1; private float lastGravity = 1;
public EntityPhysics(T entity, TrackedData<Float> gravity) { public EntityPhysics(T entity, TrackedData<Float> gravity) {
this(entity, gravity, true);
}
public EntityPhysics(T entity, TrackedData<Float> gravity, boolean register) {
this.entity = entity; this.entity = entity;
this.gravity = gravity; this.gravity = gravity;
if (register) {
this.entity.getDataTracker().startTracking(gravity, 1F);
}
} }
@Override @Override

View file

@ -19,6 +19,8 @@ public interface Equine<T extends Entity> extends NbtSerialisable, Tickable, Pro
void setSpecies(Race race); void setSpecies(Race race);
void initDataTracker();
/** /**
* Called at the beginning of an update cycle. * Called at the beginning of an update cycle.
*/ */

View file

@ -41,8 +41,12 @@ public class ItemImpl implements Equine<ItemEntity> {
public ItemImpl(ItemEntity owner) { public ItemImpl(ItemEntity owner) {
this.entity = owner; this.entity = owner;
this.physics = new ItemPhysics(owner); this.physics = new ItemPhysics(owner);
owner.getDataTracker().startTracking(ITEM_GRAVITY, 1F); }
owner.getDataTracker().startTracking(ITEM_RACE, Race.REGISTRY.getId(Race.HUMAN).toString());
@Override
public void initDataTracker() {
entity.getDataTracker().startTracking(ITEM_GRAVITY, 1F);
entity.getDataTracker().startTracking(ITEM_RACE, Race.REGISTRY.getId(Race.HUMAN).toString());
} }
@Override @Override

View file

@ -4,7 +4,7 @@ import net.minecraft.entity.ItemEntity;
class ItemPhysics extends EntityPhysics<ItemEntity> { class ItemPhysics extends EntityPhysics<ItemEntity> {
public ItemPhysics(ItemEntity entity) { public ItemPhysics(ItemEntity entity) {
super(entity, ItemImpl.ITEM_GRAVITY, false); super(entity, ItemImpl.ITEM_GRAVITY);
} }
@Override @Override

View file

@ -111,12 +111,15 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, Caste
protected Living(T entity, TrackedData<NbtCompound> effect) { protected Living(T entity, TrackedData<NbtCompound> effect) {
this.entity = entity; this.entity = entity;
this.effectDelegate = new EffectSync(this, effect); this.effectDelegate = new EffectSync(this, effect);
this.sneakingHeuristic = addTicker(new Interactable(entity::isSneaking)); this.sneakingHeuristic = addTicker(new Interactable(entity::isSneaking));
this.landedHeuristic = addTicker(new Interactable(entity::isOnGround)); this.landedHeuristic = addTicker(new Interactable(entity::isOnGround));
this.jumpingHeuristic = addTicker(new Interactable(((LivingEntityDuck)entity)::isJumping)); this.jumpingHeuristic = addTicker(new Interactable(((LivingEntityDuck)entity)::isJumping));
}
entity.getDataTracker().startTracking(effect, new NbtCompound()); @Override
public void initDataTracker() {
effectDelegate.initDataTracker();
entity.getDataTracker().startTracking(Creature.GRAVITY, 1F);
entity.getDataTracker().startTracking(CARRIER_ID, Optional.empty()); entity.getDataTracker().startTracking(CARRIER_ID, Optional.empty());
} }

View file

@ -1,19 +1,25 @@
package com.minelittlepony.unicopia.entity.mob; package com.minelittlepony.unicopia.entity.mob;
import java.util.Arrays;
import java.util.HashMap; import java.util.HashMap;
import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.function.Function;
import java.util.stream.Collectors;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds; import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.item.ButterflyItem;
import com.minelittlepony.unicopia.util.NbtSerialisable; import com.minelittlepony.unicopia.util.NbtSerialisable;
import net.minecraft.block.BlockState; import net.minecraft.block.BlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityPose; import net.minecraft.entity.EntityPose;
import net.minecraft.entity.EntityType; import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.SpawnReason; import net.minecraft.entity.SpawnReason;
import net.minecraft.entity.attribute.DefaultAttributeContainer; import net.minecraft.entity.attribute.DefaultAttributeContainer;
import net.minecraft.entity.attribute.EntityAttributes; import net.minecraft.entity.attribute.EntityAttributes;
@ -23,10 +29,13 @@ import net.minecraft.entity.data.TrackedData;
import net.minecraft.entity.data.TrackedDataHandlerRegistry; import net.minecraft.entity.data.TrackedDataHandlerRegistry;
import net.minecraft.entity.mob.AmbientEntity; import net.minecraft.entity.mob.AmbientEntity;
import net.minecraft.entity.player.PlayerEntity; import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtCompound;
import net.minecraft.predicate.entity.EntityPredicates; import net.minecraft.predicate.entity.EntityPredicates;
import net.minecraft.sound.SoundEvent; import net.minecraft.sound.SoundEvent;
import net.minecraft.registry.tag.BlockTags; import net.minecraft.registry.tag.BlockTags;
import net.minecraft.registry.tag.ItemTags;
import net.minecraft.util.Hand;
import net.minecraft.util.Identifier; import net.minecraft.util.Identifier;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@ -144,6 +153,11 @@ public class ButterflyEntity extends AmbientEntity {
if (e instanceof PlayerEntity) { if (e instanceof PlayerEntity) {
PlayerEntity player = (PlayerEntity)e; PlayerEntity player = (PlayerEntity)e;
if (player.getStackInHand(Hand.MAIN_HAND).isIn(ItemTags.FLOWERS)) {
setTarget(player);
return false;
}
if (player.isCreative() || player.isSpectator()) { if (player.isCreative() || player.isSpectator()) {
return false; return false;
} }
@ -174,6 +188,7 @@ public class ButterflyEntity extends AmbientEntity {
if (!flowerPosition.isPresent()) { if (!flowerPosition.isPresent()) {
setResting(false); setResting(false);
return; return;
} }
if (getWorld().getBlockState(below).isAir() if (getWorld().getBlockState(below).isAir()
@ -193,6 +208,17 @@ public class ButterflyEntity extends AmbientEntity {
} else { } else {
ticksResting = 0; ticksResting = 0;
if (getTarget() instanceof PlayerEntity player) {
if (player.isRemoved() || !player.getStackInHand(Hand.MAIN_HAND).isIn(ItemTags.FLOWERS)) {
setTarget(null);
}
if (distanceTo(player) > 3) {
moveTowards(player.getBlockPos());
} else {
this.addVelocity(random.nextFloat() * 0.1 - 0.05F, random.nextFloat() * 0.1, random.nextFloat() * 0.1 - 0.05F);
}
} else {
updateFlowerPosition().map(flower -> { updateFlowerPosition().map(flower -> {
if (flower.isWithinDistance(getPos(), 1)) { if (flower.isWithinDistance(getPos(), 1)) {
setResting(true); setResting(true);
@ -210,6 +236,7 @@ public class ButterflyEntity extends AmbientEntity {
} }
} }
} }
}
private boolean canBreed() { private boolean canBreed() {
return age > BREEDING_INTERVAL && breedingCooldown <= 0 && isResting() && getWorld().getOtherEntities(this, getBoundingBox().expand(2), i -> { return age > BREEDING_INTERVAL && breedingCooldown <= 0 && isResting() && getWorld().getOtherEntities(this, getBoundingBox().expand(2), i -> {
@ -304,6 +331,11 @@ public class ButterflyEntity extends AmbientEntity {
return getHeight() / 2; return getHeight() / 2;
} }
@Override
public ItemEntity dropStack(ItemStack stack, float yOffset) {
return super.dropStack(ButterflyItem.setVariant(stack, getVariant()), yOffset);
}
@Override @Override
public void writeCustomDataToNbt(NbtCompound nbt) { public void writeCustomDataToNbt(NbtCompound nbt) {
super.writeCustomDataToNbt(nbt); super.writeCustomDataToNbt(nbt);
@ -351,14 +383,14 @@ public class ButterflyEntity extends AmbientEntity {
WHITE_MONARCH, WHITE_MONARCH,
BRIMSTONE; BRIMSTONE;
private static final Variant[] VALUES = Variant.values(); public static final Variant[] VALUES = Variant.values();
private static final Map<String, Variant> REGISTRY = Arrays.stream(VALUES).collect(Collectors.toMap(a -> a.name().toLowerCase(Locale.ROOT), Function.identity()));
private final Identifier skin = Unicopia.id("textures/entity/butterfly/" + name().toLowerCase() + ".png"); private final Identifier skin = Unicopia.id("textures/entity/butterfly/" + name().toLowerCase() + ".png");
public Identifier getSkin() { public Identifier getSkin() {
return skin; return skin;
} }
static Variant byId(int index) { static Variant byId(int index) {
return VALUES[Math.max(0, index) % VALUES.length]; return VALUES[Math.max(0, index) % VALUES.length];
} }
@ -366,5 +398,9 @@ public class ButterflyEntity extends AmbientEntity {
static Variant random(Random rand) { static Variant random(Random rand) {
return VALUES[rand.nextInt(VALUES.length)]; return VALUES[rand.nextInt(VALUES.length)];
} }
public static Variant byName(String name) {
return REGISTRY.getOrDefault(name == null ? "" : name, BUTTERFLY);
}
} }
} }

View file

@ -41,12 +41,13 @@ public class Acrobatics implements Tickable, NbtSerialisable {
public Acrobatics(Pony pony) { public Acrobatics(Pony pony) {
this.pony = pony; this.pony = pony;
this.entity = pony.asEntity(); this.entity = pony.asEntity();
entity.getDataTracker().startTracking(HANGING_POSITION, Optional.empty());
pony.addTicker(this::checkDislodge); pony.addTicker(this::checkDislodge);
} }
public void initDataTracker() {
entity.getDataTracker().startTracking(HANGING_POSITION, Optional.empty());
}
public boolean isImmobile() { public boolean isImmobile() {
return isFloppy() && entity.isOnGround(); return isFloppy() && entity.isOnGround();
} }

View file

@ -38,6 +38,10 @@ class ManaContainer implements MagicReserves, Tickable, NbtSerialisable, Copyabl
}); });
} }
public void initDataTracker() {
bars.values().forEach(BarInst::initDataTracker);
}
protected BarInst addBar(String name, BarInst bar) { protected BarInst addBar(String name, BarInst bar) {
bars.put(name, bar); bars.put(name, bar);
return bar; return bar;
@ -164,7 +168,12 @@ class ManaContainer implements MagicReserves, Tickable, NbtSerialisable, Copyabl
this.marker = marker; this.marker = marker;
this.max = max; this.max = max;
this.trailingValue = initial; this.trailingValue = initial;
pony.asEntity().getDataTracker().startTracking(marker, getMax() * initial); this.prevTrailingValue = initial;
this.prevValue = initial;
}
public void initDataTracker() {
pony.asEntity().getDataTracker().startTracking(marker, max * trailingValue);
} }
@Override @Override

View file

@ -21,7 +21,6 @@ class PlayerLevelStore implements Levelled.LevelStore {
this.dataEntry = dataEntry; this.dataEntry = dataEntry;
this.upgradeMana = upgradeMana; this.upgradeMana = upgradeMana;
this.levelUpSound = levelUpSound; this.levelUpSound = levelUpSound;
pony.asEntity().getDataTracker().startTracking(dataEntry, 0);
} }
@Override @Override

View file

@ -125,15 +125,23 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
this.corruption = new PlayerLevelStore(this, CORRUPTION, false, USounds.ENTITY_PLAYER_CORRUPTION); this.corruption = new PlayerLevelStore(this, CORRUPTION, false, USounds.ENTITY_PLAYER_CORRUPTION);
this.mana = addTicker(new ManaContainer(this)); this.mana = addTicker(new ManaContainer(this));
player.getDataTracker().startTracking(RACE, Race.DEFAULT_ID);
player.getDataTracker().startTracking(SUPPRESSED_RACE, Race.DEFAULT_ID);
addTicker(this::updateAnimations); addTicker(this::updateAnimations);
addTicker(this::updateBatPonyAbilities); addTicker(this::updateBatPonyAbilities);
addTicker(this::updateCorruptionDecay); addTicker(this::updateCorruptionDecay);
addTicker(new PlayerAttributes(this)); addTicker(new PlayerAttributes(this));
} }
@Override
public void initDataTracker() {
super.initDataTracker();
acrobatics.initDataTracker();
mana.initDataTracker();
entity.getDataTracker().startTracking(LEVEL, 0);
entity.getDataTracker().startTracking(CORRUPTION, 0);
entity.getDataTracker().startTracking(RACE, Race.DEFAULT_ID);
entity.getDataTracker().startTracking(SUPPRESSED_RACE, Race.DEFAULT_ID);
}
public static void registerAttributes(DefaultAttributeContainer.Builder builder) { public static void registerAttributes(DefaultAttributeContainer.Builder builder) {
builder.add(UEntityAttributes.EXTRA_MINING_SPEED); builder.add(UEntityAttributes.EXTRA_MINING_SPEED);
builder.add(UEntityAttributes.ENTITY_GRAVITY_MODIFIER); builder.add(UEntityAttributes.ENTITY_GRAVITY_MODIFIER);

View file

@ -0,0 +1,53 @@
package com.minelittlepony.unicopia.item;
import java.util.Arrays;
import java.util.List;
import java.util.Locale;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.entity.mob.ButterflyEntity;
import com.minelittlepony.unicopia.item.group.MultiItem;
import net.minecraft.client.item.TooltipContext;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NbtCompound;
import net.minecraft.nbt.NbtElement;
import net.minecraft.text.Text;
import net.minecraft.util.Formatting;
import net.minecraft.world.World;
public class ButterflyItem extends Item implements MultiItem {
public ButterflyItem(Settings settings) {
super(settings);
}
@Override
public List<ItemStack> getDefaultStacks() {
return Arrays.stream(ButterflyEntity.Variant.VALUES).map(variant -> setVariant(getDefaultStack(), variant)).toList();
}
@Override
public void appendTooltip(ItemStack stack, @Nullable World world, List<Text> tooltip, TooltipContext context) {
tooltip.add(Text.literal(getVariant(stack).name()).formatted(Formatting.LIGHT_PURPLE));
}
public static ButterflyEntity.Variant getVariant(ItemStack stack) {
NbtCompound nbt = stack.getNbt();
if (nbt == null || !nbt.contains("variant", NbtElement.STRING_TYPE)) {
return ButterflyEntity.Variant.BUTTERFLY;
}
String variant = nbt.getString("variant");
return ButterflyEntity.Variant.byName(variant);
}
public static ItemStack setVariant(ItemStack stack, ButterflyEntity.Variant variant) {
if (stack.isOf(UItems.BUTTERFLY)) {
stack.getOrCreateNbt().putString("variant", variant.name().toLowerCase(Locale.ROOT));
}
return stack;
}
}

View file

@ -2,6 +2,8 @@ package com.minelittlepony.unicopia.item;
import com.minelittlepony.unicopia.entity.IItemEntity; import com.minelittlepony.unicopia.entity.IItemEntity;
import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.entity.mob.ButterflyEntity;
import com.minelittlepony.unicopia.entity.mob.UEntities;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity; import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import net.minecraft.block.Block; import net.minecraft.block.Block;
@ -125,8 +127,16 @@ public class FilledJarItem extends JarItem implements ChameleonItem {
@Override @Override
public void onImpact(MagicProjectileEntity projectile) { public void onImpact(MagicProjectileEntity projectile) {
ItemStack stack = getAppearanceStack(projectile.getStack()); ItemStack stack = getAppearanceStack(projectile.getStack());
if (stack.isOf(UItems.BUTTERFLY)) {
ButterflyEntity butterfly = UEntities.BUTTERFLY.create(projectile.getWorld());
butterfly.setVariant(ButterflyItem.getVariant(stack));
butterfly.updatePosition(projectile.getX(), projectile.getY(), projectile.getZ());
projectile.getWorld().spawnEntity(butterfly);
} else {
stack.damage(1, projectile.getWorld().random, null); stack.damage(1, projectile.getWorld().random, null);
projectile.dropStack(stack); projectile.dropStack(stack);
}
projectile.getWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, projectile.getBlockPos(), Block.getRawIdFromState(Blocks.GLASS.getDefaultState())); projectile.getWorld().syncWorldEvent(WorldEvents.BLOCK_BROKEN, projectile.getBlockPos(), Block.getRawIdFromState(Blocks.GLASS.getDefaultState()));
} }

View file

@ -145,7 +145,7 @@ public interface UItems {
Item LOOT_BUG_SPAWN_EGG = register("loot_bug_spawn_egg", new SpawnEggItem(UEntities.LOOT_BUG, 0x3C9D14, 0xE66F16, new Item.Settings()), ItemGroups.SPAWN_EGGS); Item LOOT_BUG_SPAWN_EGG = register("loot_bug_spawn_egg", new SpawnEggItem(UEntities.LOOT_BUG, 0x3C9D14, 0xE66F16, new Item.Settings()), ItemGroups.SPAWN_EGGS);
Item BUTTERFLY_SPAWN_EGG = register("butterfly_spawn_egg", new SpawnEggItem(UEntities.BUTTERFLY, 0x222200, 0xAAEEFF, new Item.Settings()), ItemGroups.SPAWN_EGGS); Item BUTTERFLY_SPAWN_EGG = register("butterfly_spawn_egg", new SpawnEggItem(UEntities.BUTTERFLY, 0x222200, 0xAAEEFF, new Item.Settings()), ItemGroups.SPAWN_EGGS);
Item BUTTERFLY = register("butterfly", new Item(new Item.Settings().food(UFoodComponents.INSECTS)), ItemGroups.FOOD_AND_DRINK); Item BUTTERFLY = register("butterfly", new ButterflyItem(new Item.Settings().food(UFoodComponents.INSECTS)), ItemGroups.FOOD_AND_DRINK);
Item PALM_BOAT = ItemGroupRegistry.register(TerraformBoatItemHelper.registerBoatItem(Unicopia.id("palm_boat"), UWoodTypes.PALM_BOAT_TYPE, false), ItemGroups.FUNCTIONAL); Item PALM_BOAT = ItemGroupRegistry.register(TerraformBoatItemHelper.registerBoatItem(Unicopia.id("palm_boat"), UWoodTypes.PALM_BOAT_TYPE, false), ItemGroups.FUNCTIONAL);
Item PALM_CHEST_BOAT = ItemGroupRegistry.register(TerraformBoatItemHelper.registerBoatItem(Unicopia.id("palm_chest_boat"), UWoodTypes.PALM_BOAT_TYPE, true), ItemGroups.FUNCTIONAL); Item PALM_CHEST_BOAT = ItemGroupRegistry.register(TerraformBoatItemHelper.registerBoatItem(Unicopia.id("palm_chest_boat"), UWoodTypes.PALM_BOAT_TYPE, true), ItemGroups.FUNCTIONAL);

View file

@ -19,12 +19,14 @@ import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.entity.duck.EntityDuck; import com.minelittlepony.unicopia.entity.duck.EntityDuck;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.ItemEntity; import net.minecraft.entity.ItemEntity;
import net.minecraft.entity.Entity.PositionUpdater; import net.minecraft.entity.Entity.PositionUpdater;
import net.minecraft.entity.Entity.RemovalReason; import net.minecraft.entity.Entity.RemovalReason;
import net.minecraft.fluid.Fluid; import net.minecraft.fluid.Fluid;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.registry.tag.TagKey; import net.minecraft.registry.tag.TagKey;
import net.minecraft.world.World;
@Mixin(Entity.class) @Mixin(Entity.class)
abstract class MixinEntity implements EntityDuck { abstract class MixinEntity implements EntityDuck {
@ -64,6 +66,14 @@ abstract class MixinEntity implements EntityDuck {
return self.hasVehicle() && self.getVehicle() instanceof LavaAffine affine && affine.isLavaAffine(); return self.hasVehicle() && self.getVehicle() instanceof LavaAffine affine && affine.isLavaAffine();
} }
@Inject(method = "<init>", at = @At(value = "INVOKE", target = "net/minecraft/entity/Entity.initDataTracker()V"))
private void onInstanceInit(EntityType<?> type, World world, CallbackInfo info) {
if (this instanceof Equine.Container c) {
c.get().initDataTracker();
}
}
@Inject(method = "isFireImmune", at = @At("HEAD"), cancellable = true) @Inject(method = "isFireImmune", at = @At("HEAD"), cancellable = true)
private void onIsFireImmune(CallbackInfoReturnable<Boolean> info) { private void onIsFireImmune(CallbackInfoReturnable<Boolean> info) {
if (isLavaAffine() || (this instanceof Equine.Container c) && c.get().getCompositeRace().includes(Race.KIRIN)) { if (isLavaAffine() || (this instanceof Equine.Container c) && c.get().getCompositeRace().includes(Race.KIRIN)) {

View file

@ -1,11 +1,13 @@
package com.minelittlepony.unicopia.mixin.client; package com.minelittlepony.unicopia.mixin.client;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import com.minelittlepony.unicopia.client.render.WorldRenderDelegate; import com.minelittlepony.unicopia.client.render.WorldRenderDelegate;
import com.minelittlepony.unicopia.client.render.spell.SpellEffectsRenderDispatcher;
import com.minelittlepony.unicopia.entity.Equine; import com.minelittlepony.unicopia.entity.Equine;
import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.VertexConsumerProvider;
@ -14,7 +16,7 @@ import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@Mixin(EntityRenderDispatcher.class) @Mixin(EntityRenderDispatcher.class)
abstract class MixinEntityRenderDispatcher { abstract class MixinEntityRenderDispatcher implements SpellEffectsRenderDispatcher.RenderDispatcherAccessor {
private static final String RENDER = "render(Lnet/minecraft/entity/Entity;DDDFFLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V"; private static final String RENDER = "render(Lnet/minecraft/entity/Entity;DDDFFLnet/minecraft/client/util/math/MatrixStack;Lnet/minecraft/client/render/VertexConsumerProvider;I)V";
@ -27,6 +29,10 @@ abstract class MixinEntityRenderDispatcher {
@Inject(method = RENDER, at = @At("RETURN")) @Inject(method = RENDER, at = @At("RETURN"))
private <E extends Entity> void afterRender(E entity, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo info) { private <E extends Entity> void afterRender(E entity, double x, double y, double z, float yaw, float tickDelta, MatrixStack matrices, VertexConsumerProvider vertexConsumers, int light, CallbackInfo info) {
Equine.of(entity).ifPresent(eq -> WorldRenderDelegate.INSTANCE.afterEntityRender(eq, matrices, light)); Equine.of(entity).ifPresent(eq -> WorldRenderDelegate.INSTANCE.afterEntityRender(eq, matrices, vertexConsumers, light));
} }
@Accessor("renderShadows")
@Override
public abstract boolean shouldRenderShadows();
} }

View file

@ -43,6 +43,10 @@ public class EffectSync implements SpellContainer, NbtSerialisable {
this.param = param; this.param = param;
} }
public void initDataTracker() {
owner.asEntity().getDataTracker().startTracking(param, new NbtCompound());
}
public boolean tick(Situation situation) { public boolean tick(Situation situation) {
return tick(spell -> { return tick(spell -> {
if (spell.isDying()) { if (spell.isDying()) {

View file

@ -67,7 +67,7 @@ public class MagicProjectileEntity extends ThrownItemEntity implements Caster<Ma
private final EffectSync effectDelegate = new EffectSync(this, EFFECT); private final EffectSync effectDelegate = new EffectSync(this, EFFECT);
private final EntityPhysics<MagicProjectileEntity> physics = new EntityPhysics<>(this, GRAVITY, false); private final EntityPhysics<MagicProjectileEntity> physics = new EntityPhysics<>(this, GRAVITY);
private final EntityReference<Entity> homingTarget = new EntityReference<>(); private final EntityReference<Entity> homingTarget = new EntityReference<>();
private EntityReference<LivingEntity> owner; private EntityReference<LivingEntity> owner;

View file

@ -30,7 +30,8 @@ public record Tree (
TreeFeatureConfig.Builder config, TreeFeatureConfig.Builder config,
RegistryKey<ConfiguredFeature<?, ?>> configuredFeatureId, RegistryKey<ConfiguredFeature<?, ?>> configuredFeatureId,
Set<Placement> placements, Set<Placement> placements,
Optional<Block> sapling Optional<Block> sapling,
Optional<Block> pot
) { ) {
public static final List<Tree> REGISTRY = new ArrayList<>(); public static final List<Tree> REGISTRY = new ArrayList<>();
@ -131,6 +132,7 @@ public record Tree (
public Tree build() { public Tree build() {
RegistryKey<ConfiguredFeature<?, ?>> configuredFeatureId = RegistryKey.of(RegistryKeys.CONFIGURED_FEATURE, id); RegistryKey<ConfiguredFeature<?, ?>> configuredFeatureId = RegistryKey.of(RegistryKeys.CONFIGURED_FEATURE, id);
Optional<Block> sapling = saplingId.map(id -> UBlocks.register(id, saplingConstructor.apply(new SaplingGenerator(id.toString(), Optional.of(configuredFeatureId), Optional.empty(), Optional.empty()), FabricBlockSettings.copy(Blocks.OAK_SAPLING)), ItemGroups.NATURAL));
Tree tree = new Tree(id, configParameters.apply(new TreeFeatureConfig.Builder( Tree tree = new Tree(id, configParameters.apply(new TreeFeatureConfig.Builder(
BlockStateProvider.of(logType), BlockStateProvider.of(logType),
trunkPlacer, trunkPlacer,
@ -139,7 +141,12 @@ public record Tree (
size.get() size.get()
)), configuredFeatureId, placements.values().stream() )), configuredFeatureId, placements.values().stream()
.collect(Collectors.toUnmodifiableSet()), .collect(Collectors.toUnmodifiableSet()),
saplingId.map(id -> UBlocks.register(id, saplingConstructor.apply(new SaplingGenerator(id.toString(), Optional.of(configuredFeatureId), Optional.empty(), Optional.empty()), FabricBlockSettings.copy(Blocks.OAK_SAPLING)), ItemGroups.NATURAL))); sapling,
sapling.map(saplingBlock -> {
Block flowerPot = Registry.register(Registries.BLOCK, saplingId.get().withPrefixedPath("potted_"), Blocks.createFlowerPotBlock(saplingBlock));
UBlocks.TRANSLUCENT_BLOCKS.add(flowerPot);
return flowerPot;
}));
if (REGISTRY.isEmpty()) { if (REGISTRY.isEmpty()) {
bootstrap(); bootstrap();

View file

@ -48,7 +48,7 @@ public interface UTreeGen {
Tree SWEET_APPLE_TREE = createAppleTree("sweet_apple", UBlocks.SWEET_APPLE_LEAVES, 3, 0.1F) Tree SWEET_APPLE_TREE = createAppleTree("sweet_apple", UBlocks.SWEET_APPLE_LEAVES, 3, 0.1F)
.placement("orchard", 6, 0.1F, 3, BiomeSelectors.includeByKey(UWorldGen.SWEET_APPLE_ORCHARD)) .placement("orchard", 6, 0.1F, 3, BiomeSelectors.includeByKey(UWorldGen.SWEET_APPLE_ORCHARD))
.build(); .build();
Tree SOUR_APPLE_TREE = createAppleTree("sour_apple", UBlocks.SOUR_APPLE_LEAVES, 5, 0.2F).build(); Tree SOUR_APPLE_TREE = createAppleTree("sour_apple", UBlocks.SOUR_APPLE_LEAVES, 3, 0.2F).build();
Tree GOLDEN_APPLE_TREE = Tree.Builder.create(Unicopia.id("golden_oak_tree"), Tree GOLDEN_APPLE_TREE = Tree.Builder.create(Unicopia.id("golden_oak_tree"),
new StraightTrunkPlacer(6, 1, 3), new StraightTrunkPlacer(6, 1, 3),
new BlobFoliagePlacer(ConstantIntProvider.create(3), ConstantIntProvider.create(0), 3) new BlobFoliagePlacer(ConstantIntProvider.create(3), ConstantIntProvider.create(0), 3)

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "unicopia:block/potted_golden_oak_sapling"
}
}
}

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "unicopia:block/potted_green_apple_sapling"
}
}
}

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "unicopia:block/potted_mango_sapling"
}
}
}

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "unicopia:block/potted_palm_sapling"
}
}
}

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "unicopia:block/potted_sour_apple_sapling"
}
}
}

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "unicopia:block/potted_sweet_apple_sapling"
}
}
}

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "unicopia:block/potted_zapling"
}
}
}

View file

@ -228,6 +228,7 @@
"block.unicopia.spectral_fire": "Spectral Fire", "block.unicopia.spectral_fire": "Spectral Fire",
"block.unicopia.bananas": "Bananas", "block.unicopia.bananas": "Bananas",
"block.unicopia.zapling": "Zapling", "block.unicopia.zapling": "Zapling",
"block.unicopia.potted_zapling": "Potted Zapling",
"block.unicopia.zap_log": "Zap Apple Log", "block.unicopia.zap_log": "Zap Apple Log",
"block.unicopia.zap_wood": "Zap Apple Wood", "block.unicopia.zap_wood": "Zap Apple Wood",
"block.unicopia.stripped_zap_log": "Stripped Zap Apple Log", "block.unicopia.stripped_zap_log": "Stripped Zap Apple Log",
@ -251,6 +252,7 @@
"block.unicopia.zap_apple": "Zap Apple", "block.unicopia.zap_apple": "Zap Apple",
"block.unicopia.zap_bulb": "Unripened Zap Apple", "block.unicopia.zap_bulb": "Unripened Zap Apple",
"block.unicopia.palm_sapling": "Palm Sapling", "block.unicopia.palm_sapling": "Palm Sapling",
"block.unicopia.potted_palm_sapling": "Potted Palm Sapling",
"block.unicopia.palm_log": "Palm Log", "block.unicopia.palm_log": "Palm Log",
"block.unicopia.palm_wood": "Palm Wood", "block.unicopia.palm_wood": "Palm Wood",
"block.unicopia.palm_planks": "Palm Planks", "block.unicopia.palm_planks": "Palm Planks",
@ -273,11 +275,13 @@
"block.unicopia.gold_root": "Gold Root", "block.unicopia.gold_root": "Gold Root",
"block.unicopia.golden_oak_sprout": "Golden Oak Sprout", "block.unicopia.golden_oak_sprout": "Golden Oak Sprout",
"block.unicopia.golden_oak_sapling": "Golden Oak Sapling", "block.unicopia.golden_oak_sapling": "Golden Oak Sapling",
"block.unicopia.potted_golden_oak_sapling": "Potted Golden Oak Sapling",
"block.unicopia.golden_oak_leaves": "Golden Oak Leaves", "block.unicopia.golden_oak_leaves": "Golden Oak Leaves",
"block.unicopia.golden_oak_log": "Golden Oak Log", "block.unicopia.golden_oak_log": "Golden Oak Log",
"block.unicopia.mango": "Mango", "block.unicopia.mango": "Mango",
"block.unicopia.mango_leaves": "Mango Leaves", "block.unicopia.mango_leaves": "Mango Leaves",
"block.unicopia.mango_sapling": "Mango Sapling", "block.unicopia.mango_sapling": "Mango Sapling",
"block.unicopia.potted_mango_sapling": "Potted Mango Sapling",
"block.unicopia.pineapple": "Pineapple Plant", "block.unicopia.pineapple": "Pineapple Plant",
"block.unicopia.clam_shell": "Clam Shell", "block.unicopia.clam_shell": "Clam Shell",
@ -286,12 +290,15 @@
"block.unicopia.green_apple_leaves": "Granny Smith Leaves", "block.unicopia.green_apple_leaves": "Granny Smith Leaves",
"block.unicopia.green_apple_sapling": "Granny Smith Sapling", "block.unicopia.green_apple_sapling": "Granny Smith Sapling",
"block.unicopia.potted_green_apple_sapling": "Potted Granny Smith Sapling",
"block.unicopia.green_apple_sprout": "Granny Smith Sprout", "block.unicopia.green_apple_sprout": "Granny Smith Sprout",
"block.unicopia.sweet_apple_leaves": "Sweet Apple Leaves", "block.unicopia.sweet_apple_leaves": "Sweet Apple Leaves",
"block.unicopia.sweet_apple_sapling": "Sweet Apple Sapling", "block.unicopia.sweet_apple_sapling": "Sweet Apple Sapling",
"block.unicopia.potted_sweet_apple_sapling": "Potted Sweet Apple Sapling",
"block.unicopia.sweet_apple_sprout": "Sweet Apple Sprout", "block.unicopia.sweet_apple_sprout": "Sweet Apple Sprout",
"block.unicopia.sour_apple_leaves": "Sour Apple Leaves", "block.unicopia.sour_apple_leaves": "Sour Apple Leaves",
"block.unicopia.sour_apple_sapling": "Sour Apple Sapling", "block.unicopia.sour_apple_sapling": "Sour Apple Sapling",
"block.unicopia.potted_sour_apple_sapling": "Potted Sour Apple Sapling",
"block.unicopia.sour_apple_sprout": "Sour Apple Sprout", "block.unicopia.sour_apple_sprout": "Sour Apple Sprout",
"block.unicopia.surface_chitin": "Surface Chitin", "block.unicopia.surface_chitin": "Surface Chitin",

View file

@ -301,11 +301,11 @@
"block.unicopia.chitin": "几丁质块", "block.unicopia.chitin": "几丁质块",
"block.unicopia.chitin_spikes": "几丁质尖刺", "block.unicopia.chitin_spikes": "几丁质尖刺",
"block.unicopia.chiselled_chitin": "雕纹几丁质块", "block.unicopia.chiselled_chitin": "雕纹几丁质块",
"block.unicopia.chiselled_chitin_hull": "雕纹几丁质船体", "block.unicopia.chiselled_chitin_hull": "雕纹几丁质",
"block.unicopia.chiselled_chitin_slab": "雕纹几丁质台阶", "block.unicopia.chiselled_chitin_slab": "雕纹几丁质台阶",
"block.unicopia.chiselled_chitin_stairs": "雕纹几丁质楼梯", "block.unicopia.chiselled_chitin_stairs": "雕纹几丁质楼梯",
"block.unicopia.shaping_bench": "塑形长椅", "block.unicopia.shaping_bench": "塑形",
"block.unicopia.cloud": "浮云", "block.unicopia.cloud": "浮云",
"block.unicopia.cloud_slab": "云台阶", "block.unicopia.cloud_slab": "云台阶",
"block.unicopia.cloud_stairs": "云楼梯", "block.unicopia.cloud_stairs": "云楼梯",
@ -382,7 +382,7 @@
"effect.unicopia.change_race_hippogriff": "转生骏鹰", "effect.unicopia.change_race_hippogriff": "转生骏鹰",
"effect.unicopia.morph_race_earth": "变身陆马", "effect.unicopia.morph_race_earth": "变身陆马",
"effect.unicopia.morph_race_unicopia": "变身独角兽", "effect.unicopia.morph_race_unicorn": "变身独角兽",
"effect.unicopia.morph_race_pegasus": "变身天马", "effect.unicopia.morph_race_pegasus": "变身天马",
"effect.unicopia.morph_race_changeling": "变身幻形灵", "effect.unicopia.morph_race_changeling": "变身幻形灵",
"effect.unicopia.morph_race_bat": "变身夜骐", "effect.unicopia.morph_race_bat": "变身夜骐",
@ -617,6 +617,7 @@
"tag.unicopia.food_types.desserts": "甜品", "tag.unicopia.food_types.desserts": "甜品",
"tag.unicopia.food_types.fruits_and_vegetables": "水果和蔬菜", "tag.unicopia.food_types.fruits_and_vegetables": "水果和蔬菜",
"tag.unicopia.food_types.drinks": "饮品", "tag.unicopia.food_types.drinks": "饮品",
"tag.minecraft.leaves": "叶子",
"tag.unicopia.food_types.forage_edible_filling": "大型植物料", "tag.unicopia.food_types.forage_edible_filling": "大型植物料",
"tag.unicopia.food_types.forage_edible": "植物料", "tag.unicopia.food_types.forage_edible": "植物料",

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/flower_pot_cross",
"textures": {
"plant": "unicopia:item/golden_oak_sapling"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/flower_pot_cross",
"textures": {
"plant": "unicopia:item/green_apple_sapling"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/flower_pot_cross",
"textures": {
"plant": "unicopia:item/mango_sapling"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/flower_pot_cross",
"textures": {
"plant": "unicopia:item/palm_sapling"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/flower_pot_cross",
"textures": {
"plant": "unicopia:item/sour_apple_sapling"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/flower_pot_cross",
"textures": {
"plant": "unicopia:item/sweet_apple_sapling"
}
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:block/flower_pot_cross",
"textures": {
"plant": "unicopia:item/zapling"
}
}

View file

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

View file

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

View file

@ -2,5 +2,21 @@
"parent": "unicopia:item/mug", "parent": "unicopia:item/mug",
"textures": { "textures": {
"layer0": "unicopia:item/butterfly" "layer0": "unicopia:item/butterfly"
} },
"overrides": [
{ "predicate": { "variant": 0.0666666666}, "model": "unicopia:item/yellow_butterfly" },
{ "predicate": { "variant": 0.1333333333}, "model": "unicopia:item/lime_butterfly" },
{ "predicate": { "variant": 0.2}, "model": "unicopia:item/red_butterfly" },
{ "predicate": { "variant": 0.2666666666}, "model": "unicopia:item/green_butterfly" },
{ "predicate": { "variant": 0.3333333333}, "model": "unicopia:item/blue_butterfly" },
{ "predicate": { "variant": 0.4}, "model": "unicopia:item/purple_butterfly" },
{ "predicate": { "variant": 0.4666666666}, "model": "unicopia:item/magenta_butterfly" },
{ "predicate": { "variant": 0.5333333333}, "model": "unicopia:item/pink_butterfly" },
{ "predicate": { "variant": 0.6}, "model": "unicopia:item/hedylidae_butterfly" },
{ "predicate": { "variant": 0.6666666666}, "model": "unicopia:item/lycaenidae_butterfly" },
{ "predicate": { "variant": 0.7333333333}, "model": "unicopia:item/nymphalidae_butterfly" },
{ "predicate": { "variant": 0.8}, "model": "unicopia:item/monarch_butterfly" },
{ "predicate": { "variant": 0.8666666666}, "model": "unicopia:item/white_monarch_butterfly" },
{ "predicate": { "variant": 0.9333333333}, "model": "unicopia:item/brimstone_butterfly" }
]
} }

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

View file

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

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 559 B

After

Width:  |  Height:  |  Size: 6.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 6.8 KiB

View file

@ -0,0 +1,36 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:flower_pot"
}
],
"rolls": 1.0
},
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "unicopia:golden_oak_sapling"
}
],
"rolls": 1.0
}
],
"random_sequence": "minecraft:blocks/potted_dead_bush"
}

View file

@ -0,0 +1,36 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:flower_pot"
}
],
"rolls": 1.0
},
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "unicopia:green_apple_sapling"
}
],
"rolls": 1.0
}
],
"random_sequence": "minecraft:blocks/potted_dead_bush"
}

View file

@ -0,0 +1,36 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:flower_pot"
}
],
"rolls": 1.0
},
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "unicopia:mango_sapling"
}
],
"rolls": 1.0
}
],
"random_sequence": "minecraft:blocks/potted_dead_bush"
}

View file

@ -0,0 +1,36 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:flower_pot"
}
],
"rolls": 1.0
},
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "unicopia:palm_sapling"
}
],
"rolls": 1.0
}
],
"random_sequence": "minecraft:blocks/potted_dead_bush"
}

View file

@ -0,0 +1,36 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:flower_pot"
}
],
"rolls": 1.0
},
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "unicopia:sour_apple_sapling"
}
],
"rolls": 1.0
}
],
"random_sequence": "minecraft:blocks/potted_dead_bush"
}

View file

@ -0,0 +1,36 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:flower_pot"
}
],
"rolls": 1.0
},
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "unicopia:sweet_apple_sapling"
}
],
"rolls": 1.0
}
],
"random_sequence": "minecraft:blocks/potted_dead_bush"
}

View file

@ -0,0 +1,36 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "minecraft:flower_pot"
}
],
"rolls": 1.0
},
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "unicopia:zapling"
}
],
"rolls": 1.0
}
],
"random_sequence": "minecraft:blocks/potted_dead_bush"
}

View file

@ -0,0 +1,55 @@
{
"type": "minecraft:block",
"pools": [
{
"rolls": 1.0,
"bonus_rolls": 0.0,
"entries": [
{
"type": "minecraft:item",
"name": "unicopia:slime_pustule"
}
],
"conditions": [
{
"condition": "minecraft:all_of",
"terms": [
{
"block": "unicopia:slime_pustule",
"condition": "minecraft:block_state_property",
"properties": {
"shape": "pod"
}
},
{
"condition": "minecraft:any_of",
"terms": [
{
"condition": "minecraft:match_tool",
"predicate": {
"items": [
"minecraft:shears"
]
}
},
{
"condition": "minecraft:match_tool",
"predicate": {
"enchantments": [
{
"enchantment": "minecraft:silk_touch",
"levels": {
"min": 1
}
}
]
}
}
]
}
]
}
]
}
]
}