From 5b3a8bee954ebcf60f33375c51babba10c0d4a1e Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 14:43:49 +0100 Subject: [PATCH 001/110] Limit AOE spell radius to 32 blocks. Fixes #450 --- .../unicopia/ability/magic/spell/AbstractAreaEffectSpell.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java index 1425a6ae..464b517a 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractAreaEffectSpell.java @@ -8,8 +8,10 @@ import com.minelittlepony.unicopia.ability.magic.spell.attribute.TooltipFactory; import com.minelittlepony.unicopia.ability.magic.spell.effect.*; import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait; +import net.minecraft.util.math.MathHelper; + public abstract class AbstractAreaEffectSpell extends AbstractSpell { - protected static final SpellAttribute RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 4 + power)); + protected static final SpellAttribute RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> MathHelper.clamp(4 + power, 0, 32)); public static final TooltipFactory TOOLTIP = RANGE; protected AbstractAreaEffectSpell(CustomisedSpellType type) { From fab6e7b3dd5c607101854346998df5ae0167d2ce Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 14:52:00 +0100 Subject: [PATCH 002/110] You can no longer place spellbooks in occupied blocks. Fixes #451 --- .../unicopia/item/SpellbookItem.java | 37 ++++++++++++------- 1 file changed, 24 insertions(+), 13 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/item/SpellbookItem.java b/src/main/java/com/minelittlepony/unicopia/item/SpellbookItem.java index 19a78a66..78bc3701 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/SpellbookItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/SpellbookItem.java @@ -20,6 +20,8 @@ import net.minecraft.util.TypedActionResult; import net.minecraft.util.math.BlockPointer; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Direction; +import net.minecraft.util.math.Position; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class SpellbookItem extends BookItem implements Dispensable { @@ -29,15 +31,18 @@ public class SpellbookItem extends BookItem implements Dispensable { } @Override - public TypedActionResult dispenseStack(BlockPointer source, ItemStack stack) { - Direction facing = source.getBlockState().get(DispenserBlock.FACING); - BlockPos pos = source.getPos().offset(facing); + public TypedActionResult dispenseStack(BlockPointer pointer, ItemStack stack) { + Direction facing = pointer.getBlockState().get(DispenserBlock.FACING); + Position pos = DispenserBlock.getOutputLocation(pointer); float yaw = facing.getOpposite().asRotation(); - placeBook(stack, source.getWorld(), pos.getX(), pos.getY(), pos.getZ(), yaw, null); - stack.decrement(1); + if (placeBook(stack, pointer.getWorld(), pos, yaw, null)) { + stack.decrement(1); - return new TypedActionResult<>(ActionResult.SUCCESS, stack); + return new TypedActionResult<>(ActionResult.SUCCESS, stack); + } + + return new TypedActionResult<>(ActionResult.FAIL, stack); } @Override @@ -49,24 +54,28 @@ public class SpellbookItem extends BookItem implements Dispensable { if (!context.getWorld().isClient) { BlockPos pos = context.getBlockPos().offset(context.getSide()); - placeBook(context.getStack(), context.getWorld(), pos.getX(), pos.getY(), pos.getZ(), context.getPlayerYaw() + 180, player); + if (placeBook(context.getStack(), context.getWorld(), Vec3d.ofBottomCenter(pos), context.getPlayerYaw() + 180, player)) { + if (!player.getAbilities().creativeMode) { + player.getStackInHand(context.getHand()).decrement(1); + } - if (!player.getAbilities().creativeMode) { - player.getStackInHand(context.getHand()).decrement(1); + return ActionResult.SUCCESS; } - - return ActionResult.SUCCESS; } return ActionResult.PASS; } - private static void placeBook(ItemStack stack, World world, int x, int y, int z, float yaw, @Nullable Entity placer) { + private static boolean placeBook(ItemStack stack, World world, Position pos, float yaw, @Nullable Entity placer) { SpellbookEntity book = UEntities.SPELLBOOK.create(world); - book.refreshPositionAndAngles(x + 0.5, y, z + 0.5, 0, 0); + book.refreshPositionAndAngles(pos.getX(), pos.getY(), pos.getZ(), 0, 0); book.setHeadYaw(yaw); book.setYaw(yaw); + if (!book.canSpawn(world)) { + return false; + } + @Nullable NbtCompound tag = stack.getSubNbt("spellbookState"); if (tag != null) { @@ -80,6 +89,8 @@ public class SpellbookItem extends BookItem implements Dispensable { altar.generateDecorations(world); UCriteria.LIGHT_ALTAR.trigger(placer); }); + + return true; } } From b3068780aef9521c92d1dea39a045ce322746547 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 15:30:46 +0100 Subject: [PATCH 003/110] Fixed server flight state desync. Fixes #430, Fixes #421 (probably, cannot reproduce) --- .../minelittlepony/unicopia/entity/player/PlayerPhysics.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index c2789be6..d1339e66 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -242,7 +242,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab public void tick() { super.tick(); - if (pony.isClientPlayer() && isFlying() && (pony.getJumpingHeuristic().hasChanged(Heuristic.ONCE) || pony.sneakingChanged())) { + if (pony.isClientPlayer() && (pony.getJumpingHeuristic().hasChanged(Heuristic.ONCE) || pony.sneakingChanged())) { Channel.FLIGHT_CONTROLS_INPUT.sendToServer(new MsgPlayerFlightControlsInput(pony)); } @@ -369,7 +369,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab pony.getMagicalReserves().getCharge().set(0); } - if (!creative) { + if (!creative && !pony.isClient()) { checkAvianTakeoffConditions(velocity); } } From b53a51173c38e26437e3184d3dbcdbf870f2b662 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 16:59:41 +0100 Subject: [PATCH 004/110] Updated hud texture and added page indicators. Fixes #415 --- .../unicopia/client/gui/Slot.java | 13 +++---------- .../unicopia/client/gui/UHud.java | 18 ++++++++++++++---- .../assets/unicopia/textures/gui/hud.png | Bin 34102 -> 34038 bytes 3 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/Slot.java b/src/main/java/com/minelittlepony/unicopia/client/gui/Slot.java index 80b7ef78..ced749de 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/Slot.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/Slot.java @@ -14,6 +14,7 @@ import com.mojang.blaze3d.systems.RenderSystem; import net.minecraft.client.gui.DrawContext; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.text.MutableText; +import net.minecraft.util.Colors; import net.minecraft.util.Formatting; import net.minecraft.util.math.MathHelper; @@ -145,10 +146,7 @@ class Slot { return; } - MutableText label = KeyBindingsHandler.INSTANCE.getBinding(aSlot).getLabel().copy().formatted(Formatting.BOLD); - - MatrixStack matrices = context.getMatrices(); - matrices.push(); + MutableText label = KeyBindingsHandler.INSTANCE.getBinding(aSlot).getLabel().copy(); int x = getX(); if (uHud.xDirection > 0) { @@ -158,9 +156,6 @@ class Slot { x -= uHud.client.textRenderer.getWidth(label)/2; } - matrices.translate(x, getY() + labelY, 0); - matrices.scale(0.5F, 0.5F, 0.5F); - ActivationType activation = KeyBindingsHandler.INSTANCE.getForcedActivationType(); if (activation.isResult()) { label = label.append("+T" + activation.getTapCount()); @@ -169,8 +164,6 @@ class Slot { } } - context.drawText(uHud.font, label, 0, 0, 0xFFFFFF, true); - - matrices.pop(); + DrawableUtil.drawScaledText(context, label, x, getY() + labelY, 0.5F, Colors.WHITE); } } \ No newline at end of file diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java index 1dd0ae28..590ed1e7 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java @@ -51,8 +51,8 @@ public class UHud { private final List slots = List.of( new ManaRingSlot(this, AbilitySlot.PRIMARY, AbilitySlot.PASSIVE, 0, 0), - new Slot(this, AbilitySlot.SECONDARY, AbilitySlot.SECONDARY, 30, -8), - new Slot(this, AbilitySlot.TERTIARY, AbilitySlot.TERTIARY, 40, 18) + new Slot(this, AbilitySlot.SECONDARY, AbilitySlot.SECONDARY, 30, -10), + new Slot(this, AbilitySlot.TERTIARY, AbilitySlot.TERTIARY, 43, 10) ); @Nullable @@ -137,9 +137,11 @@ public class UHud { slots.forEach(slot -> slot.renderBackground(context, abilities, swap, tickDelta)); + int currentPage = Unicopia.getConfig().hudPage.get(); + int maxPages = pony.getAbilities().getMaxPage(); Ability ability = pony.getAbilities().getStat(AbilitySlot.PRIMARY) - .getAbility(Unicopia.getConfig().hudPage.get()) + .getAbility(currentPage) .orElse(null); boolean canCast = ability == Abilities.CAST || ability == Abilities.KIRIN_CAST || ability == Abilities.SHOOT; @@ -168,6 +170,14 @@ public class UHud { slots.forEach(slot -> slot.renderLabel(context, abilities, tickDelta)); + //if (maxPages > 0) { + DrawableUtil.drawScaledText(context, Text.literal((currentPage + 1) + "/" + (maxPages + 1)), 44, 38, 0.5F, Colors.WHITE); + //down + context.drawTexture(HUD_TEXTURE, 42, 43, 52, currentPage == 0 ? 6 : 0, 6, 6, 128, 128); + //up + context.drawTexture(HUD_TEXTURE, 48, 43, 57, currentPage < maxPages ? 0 : 6, 8, 6, 128, 128); + //} + matrices.pop(); if (canCast) { @@ -188,7 +198,7 @@ public class UHud { int progress = Math.min(255, (int)(time * 255F / 20F)); if (progress > 8) { - int color = 0xFFFFFF; + int color = Colors.WHITE; int alpha = progress << 24 & -16777216; color |= alpha; diff --git a/src/main/resources/assets/unicopia/textures/gui/hud.png b/src/main/resources/assets/unicopia/textures/gui/hud.png index 7070f5ad3a7515d960cfd7d998a61611539e98ab..6fcab1f6c4636c2956df5e9d771c5e0ed64cf64f 100644 GIT binary patch literal 34038 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 literal 34102 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⪚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 Date: Mon, 16 Sep 2024 17:17:21 +0100 Subject: [PATCH 005/110] Fixed bat ponies unable to sleep at night when there is a thunderstorm. Fixes #436 --- .../java/com/minelittlepony/unicopia/entity/player/Pony.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index cfe236a9..4cc2b251 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -807,7 +807,7 @@ public class Pony extends Living implements Copyable, Update public ActionResult canSleepNow() { if (asWorld().getGameRules().getBoolean(UGameRules.DO_NOCTURNAL_BAT_PONIES) && getSpecies().isNocturnal()) { - return asWorld().isDay() ? ActionResult.SUCCESS : ActionResult.FAIL; + return asWorld().isDay() || asWorld().getAmbientDarkness() >= 4 ? ActionResult.SUCCESS : ActionResult.FAIL; } return ActionResult.PASS; From 0ba3fd64a7b1bedd5ff48537d5b5f97aa0590e7f Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 17:51:41 +0100 Subject: [PATCH 006/110] Fixed earth ponies breaking blocks in adventure mode and protected regions. Fixes #434 --- .../unicopia/ability/EarthPonyGrowAbility.java | 5 ++++- .../unicopia/ability/EarthPonyKickAbility.java | 15 +++++++++++---- .../unicopia/ability/EarthPonyStompAbility.java | 15 ++++++++------- .../unicopia/entity/player/PlayerPhysics.java | 6 +++--- .../unicopia/entity/player/Pony.java | 2 +- .../server/world/BlockDestructionManager.java | 3 ++- 6 files changed, 29 insertions(+), 17 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java index 744ee4a5..386fa26a 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java @@ -14,6 +14,7 @@ import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.recipe.TransformCropsRecipe; import com.minelittlepony.unicopia.recipe.URecipes; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; +import com.minelittlepony.unicopia.server.world.ModificationType; import com.minelittlepony.unicopia.util.TraceHelper; import com.minelittlepony.unicopia.util.VecHelper; @@ -70,7 +71,9 @@ public class EarthPonyGrowAbility implements Ability { for (BlockPos pos : BlockPos.iterate( data.pos().add(-2, -2, -2), data.pos().add( 2, 2, 2))) { - count += applySingle(player, player.asWorld(), player.asWorld().getBlockState(pos), pos); + if (player.canModifyAt(pos, ModificationType.PHYSICAL)) { + count += applySingle(player, player.asWorld(), player.asWorld().getBlockState(pos), pos); + } } } else { count = 1; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java index ca76579f..f8e4e861 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyKickAbility.java @@ -17,6 +17,7 @@ import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; +import com.minelittlepony.unicopia.server.world.ModificationType; import com.minelittlepony.unicopia.util.*; import net.minecraft.block.BeehiveBlock; @@ -98,7 +99,7 @@ public class EarthPonyKickAbility implements Ability { } BlockPos pos = kickLocation.pos(); - EarthPonyStompAbility.stompBlock(w, pos, 10 * (1 + player.getLevel().getScaled(5)) * w.getBlockState(pos).calcBlockBreakingDelta(player.asEntity(), w, pos)); + EarthPonyStompAbility.stompBlock(player, w, pos, 10 * (1 + player.getLevel().getScaled(5)) * w.getBlockState(pos).calcBlockBreakingDelta(player.asEntity(), w, pos)); player.setAnimation(Animation.KICK, Animation.Recipient.ANYONE); }); } @@ -165,10 +166,16 @@ public class EarthPonyKickAbility implements Ability { if (BlockDestructionManager.of(player.getWorld()).getBlockDestruction(pos) + 4 >= BlockDestructionManager.MAX_DAMAGE) { if (player.getWorld().random.nextInt(30) == 0) { - tree.logs().forEach(player.getWorld(), (w, state, p) -> w.breakBlock(p, true)); + tree.logs().forEach(player.getWorld(), (w, state, p) -> { + if (iplayer.canModifyAt(p, ModificationType.PHYSICAL)) { + w.breakBlock(p, true); + } + }); tree.leaves().forEach(player.getWorld(), (w, state, p) -> { - Block.dropStacks(w.getBlockState(p), w, p); - w.setBlockState(p, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL); + if (iplayer.canModifyAt(p, ModificationType.PHYSICAL)) { + Block.dropStacks(w.getBlockState(p), w, p); + w.setBlockState(p, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL); + } }); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java index de4c8be8..e1761d25 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyStompAbility.java @@ -19,6 +19,7 @@ import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.particle.ParticleUtils; import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; +import com.minelittlepony.unicopia.server.world.ModificationType; import com.minelittlepony.unicopia.util.PosHelper; import com.minelittlepony.unicopia.util.VecHelper; @@ -166,7 +167,7 @@ public class EarthPonyStompAbility implements Ability { double radius = rad + heavyness * 0.3; - spawnEffectAround(player, center, radius, rad); + spawnEffectAround(iplayer, player, center, radius, rad); ParticleUtils.spawnParticle(player.getWorld(), UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0); BlockState steppingState = player.getSteppingBlockState(); @@ -198,17 +199,17 @@ public class EarthPonyStompAbility implements Ability { return true; } - public static void spawnEffectAround(Entity source, BlockPos center, double radius, double range) { + public static void spawnEffectAround(Pony pony, Entity source, BlockPos center, double radius, double range) { BlockPos.stream(new BlockBox(center).expand(MathHelper.ceil(radius))).forEach(i -> { double dist = Math.sqrt(i.getSquaredDistance(source.getX(), source.getY(), source.getZ())); if (dist <= radius) { - spawnEffect(source.getWorld(), i, dist, range); + spawnEffect(pony, source.getWorld(), i, dist, range); } }); } - public static void spawnEffect(World w, BlockPos pos, double dist, double rad) { + public static void spawnEffect(Pony pony, World w, BlockPos pos, double dist, double rad) { if (w.getBlockState(pos.up()).isAir()) { BlockState state = w.getBlockState(pos); @@ -216,18 +217,18 @@ public class EarthPonyStompAbility implements Ability { float scaledHardness = (1 - hardness / 70); float damage = hardness < 0 ? 0 : MathHelper.clamp((int)((1 - dist / rad) * 9 * scaledHardness), 0, BlockDestructionManager.MAX_DAMAGE - 1); - stompBlock(w, pos, damage); + stompBlock(pony, w, pos, damage); } } - public static void stompBlock(World w, BlockPos pos, float damage) { + public static void stompBlock(Pony pony, World w, BlockPos pos, float damage) { BlockState state = w.getBlockState(pos); if (state.isAir() || damage <= 0) { return; } - if (BlockDestructionManager.of(w).damageBlock(pos, damage) >= BlockDestructionManager.MAX_DAMAGE) { + if (BlockDestructionManager.of(w).damageBlock(pos, damage) >= BlockDestructionManager.MAX_DAMAGE && pony.canModifyAt(pos, ModificationType.PHYSICAL)) { w.breakBlock(pos, true); if (w instanceof ServerWorld) { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index d1339e66..ca77955d 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -829,8 +829,8 @@ public class PlayerPhysics extends EntityPhysics implements Tickab .reduce(0, (u, pos) -> { if (pony.canModifyAt(pos, ModificationType.PHYSICAL)) { if (isEarthPonySmash) { - BlockDestructionManager.of(entity.getWorld()).damageBlock(pos, (int)entity.getWorld().getRandom().nextTriangular(5, 3)); - if (BlockDestructionManager.of(entity.getWorld()).getBlockDestruction(pos) >= 9) { + float destruction = BlockDestructionManager.of(entity.getWorld()).damageBlock(pos, (int)entity.getWorld().getRandom().nextTriangular(5, 3)); + if (destruction >= BlockDestructionManager.MAX_DAMAGE - 1 && pony.canModifyAt(pos, ModificationType.PHYSICAL)) { entity.getWorld().breakBlock(pos, true); } } else { @@ -862,7 +862,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab if (isFlying()) { playSound(USounds.ENTITY_PLAYER_PEGASUS_DASH, 1, 1); } else { - playSound(USounds.ENTITY_PLAYER_EARTHPONY_DASH, 2, 0.3F); + playSound(USounds.ENTITY_PLAYER_EARTHPONY_DASH, 2, 1.3F); } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index 4cc2b251..9d09beaa 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -703,7 +703,7 @@ public class Pony extends Living implements Copyable, Update if (EffectUtils.hasExtraDefenses(entity)) { double radius = distance / 10; if (radius > 0) { - EarthPonyStompAbility.spawnEffectAround(entity, entity.getSteppingPos(), radius, radius); + EarthPonyStompAbility.spawnEffectAround(this, entity, entity.getSteppingPos(), radius, radius); } } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/BlockDestructionManager.java b/src/main/java/com/minelittlepony/unicopia/server/world/BlockDestructionManager.java index 974abaef..25464839 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/BlockDestructionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/BlockDestructionManager.java @@ -17,6 +17,7 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; public class BlockDestructionManager implements Tickable { @@ -54,7 +55,7 @@ public class BlockDestructionManager implements Tickable { if (amount == 0) { return getBlockDestruction(pos); } - amount = Math.max(getBlockDestruction(pos), 0) + amount; + amount = MathHelper.clamp(Math.max(getBlockDestruction(pos), 0) + amount, 0, MAX_DAMAGE); setBlockDestruction(pos, amount); return amount; } From 6f9af460600553015c29d5a616ff10148e909ed0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 17:53:02 +0100 Subject: [PATCH 007/110] Fixed sounds not playing when dashing --- .../minelittlepony/unicopia/entity/player/PlayerPhysics.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index ca77955d..59eb9d80 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -530,7 +530,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab } private void playSound(SoundEvent sound, float volume, float pitch) { - entity.getWorld().playSoundFromEntity(entity, entity, sound, SoundCategory.PLAYERS, volume, pitch); + entity.getWorld().playSoundFromEntity(entity.getWorld().isClient ? entity : null, entity, sound, SoundCategory.PLAYERS, volume, pitch); } private void tickNaturalFlight(MutableVector velocity) { From 7c779eb2e39f2e7d03117390293ded8996345a0c Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 17:56:55 +0100 Subject: [PATCH 008/110] Fixed feathers dropping on the client. Fixes #383 --- .../minelittlepony/unicopia/entity/player/PlayerPhysics.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index 59eb9d80..6b729dfd 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -463,7 +463,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab entity.damage(entity.getDamageSources().generic(), 0.5F); } - if (type.isAvian()) { + if (type.isAvian() && !entity.getWorld().isClient) { if (pony.getObservedSpecies() != Race.BAT && entity.getWorld().random.nextInt(9000) == 0) { entity.dropItem(pony.getObservedSpecies() == Race.HIPPOGRIFF ? UItems.GRYPHON_FEATHER : UItems.PEGASUS_FEATHER); playSound(USounds.ENTITY_PLAYER_PEGASUS_MOLT, 0.3F, 1); From d6286c7a00a5003e1fa53ad708beba7e58576755 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 18:12:58 +0100 Subject: [PATCH 009/110] Fixed player position messed up when mounting a boat whilst flying Players can now fly from boats again. Fixes #377 --- .../unicopia/ability/ToggleFlightAbility.java | 8 +++++++- .../unicopia/mixin/server/MixinServerPlayerEntity.java | 5 +++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/ToggleFlightAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/ToggleFlightAbility.java index d1a45aa2..a3c3e6fa 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/ToggleFlightAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/ToggleFlightAbility.java @@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.player.Pony; import net.minecraft.util.Identifier; +import net.minecraft.util.math.Vec3d; public class ToggleFlightAbility implements Ability { @@ -27,7 +28,7 @@ public class ToggleFlightAbility implements Ability { @Nullable @Override public Optional prepare(Pony player) { - return Hit.of(!player.asEntity().hasVehicle() && !player.asEntity().isCreative() && !player.getPhysics().getFlightType().isGrounded()); + return Hit.of(!player.asEntity().isCreative() && !player.getPhysics().getFlightType().isGrounded()); } @Override @@ -59,6 +60,11 @@ public class ToggleFlightAbility implements Ability { player.subtractEnergyCost(1); if (!player.getPhysics().isFlying()) { + if (player.asEntity().hasVehicle()) { + Vec3d pos = player.asEntity().getPos(); + player.asEntity().stopRiding(); + player.asEntity().setPosition(pos.getX(), pos.getY() + 0.25, pos.getZ()); + } player.asEntity().addVelocity(0, player.getPhysics().getGravitySignum() * 0.7F, 0); Living.updateVelocity(player.asEntity()); player.getPhysics().startFlying(true); diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinServerPlayerEntity.java b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinServerPlayerEntity.java index 2ae21fe5..30a69af2 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinServerPlayerEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinServerPlayerEntity.java @@ -52,4 +52,9 @@ abstract class MixinServerPlayerEntity extends PlayerEntity implements ScreenHan private void onUpdateKilledAdvancementCriterion(Entity entityKilled, int score, DamageSource damageSource, CallbackInfo info) { get().onKill(entityKilled, damageSource); } + + @Inject(method = "startRiding(Lnet/minecraft/entity/Entity;Z)Z", at = @At("HEAD")) + private void onStartRiding(Entity entity, boolean force, CallbackInfoReturnable info) { + get().getPhysics().cancelFlight(true); + } } From 1c52237568518f25b31ca4bd6843f55a4d5d6fde Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 19:16:05 +0100 Subject: [PATCH 010/110] Fixed changling clinging and bat pony hanging abilities. Closes #404 --- .../unicopia/ability/BatPonyHangAbility.java | 2 +- .../unicopia/entity/EntityPhysics.java | 13 ++++++------ .../unicopia/entity/player/Acrobatics.java | 21 ++++++++++++------- 3 files changed, 21 insertions(+), 15 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/BatPonyHangAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/BatPonyHangAbility.java index 723cc0f5..95566b44 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/BatPonyHangAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/BatPonyHangAbility.java @@ -37,7 +37,7 @@ public class BatPonyHangAbility implements Ability { } return TraceHelper.findBlock(player.asEntity(), 5, 1) - .map(BlockPos::down) + .map(pos -> pos.down(player.getPhysics().getGravitySignum())) .filter(player.getAcrobatics()::canHangAt) .map(pos -> new Multi(pos, 1)); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java index c50d740f..bd51d7ba 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/EntityPhysics.java @@ -10,12 +10,12 @@ import com.minelittlepony.unicopia.util.Tickable; import net.minecraft.block.BlockState; import net.minecraft.block.FenceGateBlock; import net.minecraft.entity.Entity; +import net.minecraft.entity.EntityPose; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.mob.MobEntity; import net.minecraft.nbt.NbtCompound; import net.minecraft.registry.tag.BlockTags; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; public class EntityPhysics implements Physics, Copyable>, Tickable { @@ -75,18 +75,17 @@ public class EntityPhysics implements Physics, Copyable 1.5) { @@ -156,8 +159,9 @@ public class Acrobatics implements Tickable, NbtSerialisable { } public void startHanging(BlockPos pos) { + boolean inverted = pony.getPhysics().isGravityNegative(); hangingPos.set(Optional.of(pos)); - entity.teleport(pos.getX() + 0.5, pos.getY() - 1, pos.getZ() + 0.5); + entity.teleport(pos.getX() + 0.5, pos.getY() - (inverted ? 0 : 1), pos.getZ() + 0.5); entity.setVelocity(Vec3d.ZERO); entity.setSneaking(false); entity.stopFallFlying(); @@ -165,14 +169,17 @@ public class Acrobatics implements Tickable, NbtSerialisable { } public boolean canHangAt(BlockPos pos) { - if (!pony.asWorld().isAir(pos) || !pony.asWorld().isAir(pos.down())) { + int gravity = pony.getPhysics().getGravitySignum() * (isHanging() && pony.getObservedSpecies() == Race.BAT ? -1 : 1); + BlockState state = pony.asWorld().getBlockState(pos); + + if (!pony.asWorld().isAir(pos) || !pony.asWorld().isAir(pos.down(gravity))) { return false; } - pos = pos.up(); - BlockState state = pony.asWorld().getBlockState(pos); + pos = pos.up(gravity); + state = pony.asWorld().getBlockState(pos); - return state.isSolidSurface(pony.asWorld(), pos, entity, Direction.DOWN) && entity.getWorld().isAir(entity.getBlockPos().down()); + return state.isSolidSurface(pony.asWorld(), pos, entity, gravity > 0 ? Direction.UP : Direction.DOWN); } private boolean canKeepHanging() { @@ -184,7 +191,7 @@ public class Acrobatics implements Tickable, NbtSerialisable { return true; } return getHangingPosition().filter(hangingPos -> { - return (race != Race.BAT || hangingPos.equals(pony.getOrigin().down())) && canHangAt(hangingPos); + return (race != Race.BAT || hangingPos.equals(pony.asEntity().getBlockPos().up(pony.getPhysics().isGravityNegative() ? 1 : 0))) && canHangAt(hangingPos); }).isPresent(); } From 6ac22e36a136c9e86a6dd7abb1039c6a99d1da2c Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 19:29:00 +0100 Subject: [PATCH 011/110] Fixed mobs getting stuck targetting an invalid entity. Fixes #414 --- .../com/minelittlepony/unicopia/entity/ai/BreakHeartGoal.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/ai/BreakHeartGoal.java b/src/main/java/com/minelittlepony/unicopia/entity/ai/BreakHeartGoal.java index 38328a96..a37eff54 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/ai/BreakHeartGoal.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/ai/BreakHeartGoal.java @@ -49,6 +49,7 @@ public class BreakHeartGoal extends Goal { public void stop() { targetter.stop(); mob.getNavigation().stop(); + mob.setTarget(null); } @Override From 9d03ad75769ae53379cd3f08db5294e1b8b03270 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 19:58:41 +0100 Subject: [PATCH 012/110] Fix command outputs. Fixes #435 --- .../unicopia/command/ConfigCommand.java | 7 +-- .../unicopia/command/GravityCommand.java | 14 ++--- .../unicopia/command/ManaCommand.java | 5 +- .../unicopia/command/SpeciesCommand.java | 52 ++++++++++--------- .../unicopia/command/TraitCommand.java | 5 +- 5 files changed, 44 insertions(+), 39 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/command/ConfigCommand.java b/src/main/java/com/minelittlepony/unicopia/command/ConfigCommand.java index 81b0abab..fb9b5ab2 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/ConfigCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/ConfigCommand.java @@ -23,7 +23,6 @@ import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryWrapper; import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; -import net.minecraft.server.network.ServerPlayerEntity; import net.minecraft.text.Text; import net.minecraft.util.Identifier; @@ -63,10 +62,8 @@ public class ConfigCommand { }))) ) .then(CommandManager.literal("list").executes(source -> ConfigCommand.>getProperty(configName, values -> { - ServerPlayerEntity player = source.getSource().getPlayerOrThrow(); - - player.sendMessage(Text.translatable("command.unicopia.config.list", configName, values.size()), false); - values.forEach(line -> player.sendMessage(Text.literal(line))); + source.getSource().sendFeedback(() -> Text.translatable("command.unicopia.config.list", configName, values.size()), false); + values.forEach(line -> source.getSource().sendFeedback(() -> Text.literal(line), false)); })) ); } diff --git a/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java b/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java index a97272e9..d071b6bf 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/GravityCommand.java @@ -50,17 +50,19 @@ class GravityCommand { l.getPhysics().setBaseGravityModifier(gravity); if (l.asEntity() instanceof PlayerEntity player) { if (source.getEntity() == player) { - player.sendMessage(Text.translatable("commands.gravity.set.self", gravity)); - } else if (source.getWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) { - player.sendMessage(Text.translatable("commands.gravity.set.other", l.asEntity().getDisplayName(), gravity)); + source.sendFeedback(() -> Text.translatable("commands.gravity.set.self", gravity), true); + } else { + if (source.getWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) { + player.sendMessage(Text.translatable("commands.gravity.set", gravity)); + } + + source.sendFeedback(() -> Text.translatable("commands.gravity.set.other", l.asEntity().getDisplayName(), gravity), true); } } return (Entity)l.asEntity(); }).toList(); - if (affected.size() == 1) { - source.sendFeedback(() -> Text.translatable("commands.gravity.set.other", affected.get(0).getDisplayName()), true); - } else { + if (affected.size() > 1) { source.sendFeedback(() -> Text.translatable("commands.gravity.set.multiple", affected.size()), true); } return 0; diff --git a/src/main/java/com/minelittlepony/unicopia/command/ManaCommand.java b/src/main/java/com/minelittlepony/unicopia/command/ManaCommand.java index 6383163a..18c6fd8b 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/ManaCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/ManaCommand.java @@ -23,7 +23,7 @@ public class ManaCommand { var pony = Pony.of(source.getSource().getPlayer()); var bar = type.getBar(pony.getMagicalReserves()); - source.getSource().getPlayer().sendMessage(Text.literal(type.name() + " is " + bar.get() + "/" + bar.getMax())); + source.getSource().sendFeedback(() -> Text.literal(type.name() + " is " + bar.get() + "/" + bar.getMax()), true); return 0; }) .then(CommandManager.argument("value", FloatArgumentType.floatArg()).executes(source -> { @@ -47,7 +47,8 @@ public class ManaCommand { pony.asWorld().playSound(null, pony.getOrigin(), USounds.Vanilla.ENTITY_PLAYER_LEVELUP, SoundCategory.PLAYERS, 1, 2); } bar.set(value); - source.getSource().getPlayer().sendMessage(Text.literal("Set " + type.name() + " to " + bar.get() + "/" + bar.getMax())); + var t = type; + source.getSource().sendFeedback(() -> Text.literal("Set " + t.name() + " to " + bar.get() + "/" + bar.getMax()), true); return 0; }))); } diff --git a/src/main/java/com/minelittlepony/unicopia/command/SpeciesCommand.java b/src/main/java/com/minelittlepony/unicopia/command/SpeciesCommand.java index e1e9e999..5fecdbe6 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/SpeciesCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/SpeciesCommand.java @@ -44,10 +44,10 @@ class SpeciesCommand { )) .then(CommandManager.literal("describe") .then(CommandManager.argument("race", Race.argument()).suggests(UCommandSuggestion.ALL_RACE_SUGGESTIONS) - .executes(context -> describe(context.getSource().getPlayer(), Race.fromArgument(context, "race"))) + .executes(context -> describe(context.getSource(), Race.fromArgument(context, "race"))) )) .then(CommandManager.literal("list") - .executes(context -> list(context.getSource().getPlayer()) + .executes(context -> list(context.getSource()) )); } @@ -70,57 +70,59 @@ class SpeciesCommand { } source.sendFeedback(() -> Text.translatable("commands.race.success.other", player.getName(), race.getDisplayName()), true); } - } else if (player.getEntityWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) { - player.sendMessage(Text.translatable("commands.race.permission"), false); + } else { + source.sendFeedback(() -> Text.translatable("commands.race.permission"), false); } return 0; } static int get(ServerCommandSource source, PlayerEntity player, boolean isSelf) { - Race spec = Pony.of(player).getSpecies(); + source.sendFeedback(() -> { + Race spec = Pony.of(player).getSpecies(); - String name = "commands.race.tell."; - name += isSelf ? "self" : "other"; + String name = "commands.race.tell."; + name += isSelf ? "self" : "other"; - player.sendMessage(Text.translatable(name, player.getName()) + return Text.translatable(name, player.getName()) .append(Text.translatable(spec.getTranslationKey()) - .styled(s -> s.withColor(Formatting.GOLD))), false); - + .styled(s -> s.withColor(Formatting.GOLD))); + }, false); return 0; } - static int list(PlayerEntity player) { - player.sendMessage(Text.translatable("commands.race.list"), false); + static int list(ServerCommandSource source) { + source.sendFeedback(() -> Text.translatable("commands.race.list"), false); + source.sendFeedback(() -> { + MutableText message = Text.literal(""); - MutableText message = Text.literal(""); - - boolean first = true; - for (Race i : Race.REGISTRY) { - if (i.availability().isGrantable() && !i.isUnset() && i.isPermitted(player)) { - message.append(Text.literal((!first ? "\n" : "") + " - ")); - message.append(i.getDisplayName()); - first = false; + boolean first = true; + for (Race i : Race.REGISTRY) { + if (i.availability().isGrantable() && !i.isUnset() && i.isPermitted(source.getPlayer())) { + message.append(Text.literal((!first ? "\n" : "") + " - ")); + message.append(i.getDisplayName()); + first = false; + } } - } - player.sendMessage(message.styled(s -> s.withColor(Formatting.GOLD)), false); + return message.styled(s -> s.withColor(Formatting.GOLD)); + }, false); return 0; } - static int describe(PlayerEntity player, Race species) { + static int describe(ServerCommandSource source, Race species) { Identifier id = Race.REGISTRY.getId(species); for (String category : new String[] { "goods", "bads" }) { - player.sendMessage(Text.translatable( + source.sendFeedback(() -> Text.translatable( String.format("gui.unicopia.tribe_selection.confirm.%s.%d.%s.%s", category), species.getAltDisplayName() ), false); for (int i = 1; i < 5; i++) { String line = String.format("gui.unicopia.tribe_selection.confirm.%s.%d.%s.%s", category, i, id.getNamespace(), id.getPath()); - player.sendMessage(Text.translatable(line).styled(s -> s.withColor(category.equals("goods") ? Formatting.YELLOW : Formatting.RED)), false); + source.sendFeedback(() -> Text.translatable(line).styled(s -> s.withColor(category.equals("goods") ? Formatting.YELLOW : Formatting.RED)), false); } } diff --git a/src/main/java/com/minelittlepony/unicopia/command/TraitCommand.java b/src/main/java/com/minelittlepony/unicopia/command/TraitCommand.java index 04bcf078..560eaecc 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/TraitCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/TraitCommand.java @@ -13,6 +13,7 @@ import net.minecraft.server.command.CommandManager; import net.minecraft.server.command.ServerCommandSource; import net.minecraft.text.*; import net.minecraft.util.Hand; +import net.minecraft.world.GameRules; class TraitCommand { static LiteralArgumentBuilder create() { @@ -78,7 +79,9 @@ class TraitCommand { float gravity = iplayer.getPhysics().getGravityModifier(); if (source.getPlayer() == player) { - player.sendMessage(Text.translatable(translationKey, gravity), false); + if (player.getEntityWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) { + player.sendMessage(Text.translatable(translationKey, gravity), false); + } } else { source.sendFeedback(() -> Text.translatable(translationKey + ".other", player.getName(), gravity), true); } From fe39258cffb2c3bd8a218a74c156290bb8428ae0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 20:10:38 +0100 Subject: [PATCH 013/110] Fixed crash when wearing alicorn amulet. Fixes #400 --- .../minelittlepony/unicopia/entity/AttributeContainer.java | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java b/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java index 8f94a440..85d61d88 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java @@ -26,9 +26,7 @@ public interface AttributeContainer { EntityAttributeModifier modifier = instance.getModifier(id); if (!MathHelper.approximatelyEquals(desiredValue, modifier == null ? 0 : modifier.getValue())) { - if (modifier != null) { - instance.removeModifier(modifier); - } + instance.removeModifier(id); if (desiredValue != 0) { if (permanent) { From 1b2f0ebd6b481e369da7f33e4adf038f6ba2e39e Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 20:11:19 +0100 Subject: [PATCH 014/110] Fixed crash when disguised as a mob whilst wearing an amulet. Fixes #401 --- .../unicopia/client/render/AmuletFeatureRenderer.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java index 99bce334..d5a2ffbf 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/AmuletFeatureRenderer.java @@ -49,7 +49,9 @@ public class AmuletFeatureRenderer implements AccessoryF VertexConsumer consumer = ItemRenderer.getArmorGlintConsumer(renderContext, RenderLayer.getArmorCutoutNoCull(texture), false, false); - model.setAngles(entity, context.getModel()); + if (context.getModel() instanceof BipedEntityModel) { + model.setAngles(entity, context.getModel()); + } model.render(matrices, consumer, lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1); } } From 512ae4d126d11a2c708916dea92e3ddbf4569cb7 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 20:26:07 +0100 Subject: [PATCH 015/110] Fixed bat screech effect position when ponified. Fixes #399 --- .../com/minelittlepony/unicopia/ability/ScreechAbility.java | 5 ++++- .../minelittlepony/unicopia/client/minelittlepony/Main.java | 4 +++- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/ScreechAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/ScreechAbility.java index 55b9c393..52bd6e66 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/ScreechAbility.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/ScreechAbility.java @@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.ability.data.Numeric; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.advancement.UCriteria; +import com.minelittlepony.unicopia.client.minelittlepony.MineLPDelegate; import com.minelittlepony.unicopia.client.render.PlayerPoser.Animation; import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.damage.UDamageTypes; @@ -126,8 +127,10 @@ public class ScreechAbility implements Ability { @Override public void coolDown(Pony player, AbilitySlot slot) { + Vec3d eyePos = player.asEntity().getPos().add(0, MineLPDelegate.getInstance().getPonyHeight(player.asEntity()) * 0.8, 0); + for (int i = 0; i < 20; i++) { - player.addParticle(ParticleTypes.BUBBLE_POP, player.asEntity().getEyePos(), + player.addParticle(ParticleTypes.BUBBLE_POP, eyePos, VecHelper.supply(() -> (player.asWorld().getRandom().nextGaussian() - 0.5) * 0.3) ); } diff --git a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java index 229fb3ed..4abe27c4 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java +++ b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java @@ -117,7 +117,9 @@ public class Main extends MineLPDelegate implements ClientModInitializer { @Override public float getPonyHeight(Entity entity) { - return super.getPonyHeight(entity) * IPony.getManager().getPony(entity).map(pony -> pony.metadata().getSize().getScaleFactor() + 0.1F).orElse(1F); + return super.getPonyHeight(entity) * IPony.getManager().getPony(entity) + .map(pony -> pony.race().isHuman() ? 1 : pony.metadata().getSize().getScaleFactor() + 0.1F) + .orElse(1F); } private static Race toUnicopiaRace(com.minelittlepony.api.pony.meta.Race race) { From 9424a3f2ba5f53123aa09c676906adeec371ded6 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 16 Sep 2024 20:43:43 +0100 Subject: [PATCH 016/110] Fix jar inventory size mismatch. Fixes #441 --- .../unicopia/block/jar/ItemsJarContents.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java b/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java index a406c3dd..62f39881 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java +++ b/src/main/java/com/minelittlepony/unicopia/block/jar/ItemsJarContents.java @@ -30,15 +30,16 @@ public record ItemsJarContents ( TileData tile, List stacks ) implements JarContents, SidedInventory { - private static final int[] SLOTS = IntStream.range(0, 16).toArray(); + private static final int MAX_SIZE = 16; + private static final int[] SLOTS = IntStream.range(0, MAX_SIZE).toArray(); public ItemsJarContents(TileData tile) { - this(tile, new ArrayList<>()); + this(tile, new ArrayList<>(MAX_SIZE)); } public ItemsJarContents(TileData tile, NbtCompound compound) { this(tile, NbtSerialisable.ITEM_STACK.readAll(compound.getList("items", NbtElement.COMPOUND_TYPE)) - .limit(15) + .limit(MAX_SIZE) .collect(Collectors.toList())); } @@ -115,7 +116,7 @@ public record ItemsJarContents ( @Override public int size() { - return 15; + return MAX_SIZE; } @Override From aa7c4511e9f5c57141d3dd3f7548fee11102bcaa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Wed, 18 Sep 2024 00:59:15 +0100 Subject: [PATCH 017/110] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 38 +++++++++++++++++++++++ .github/ISSUE_TEMPLATE/feature_request.md | 26 ++++++++++++++++ 2 files changed, 64 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/bug_report.md create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md new file mode 100644 index 00000000..50c1f090 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -0,0 +1,38 @@ +--- +name: Bug report +about: Create a report to help us improve +title: "[BUG]" +labels: bug +assignees: Sollace + +--- + +**Describe the bug** +A clear and concise description of what the bug is. + +**Expected behavior** +A clear and concise description of what you expected to happen. + +**Steps to reproduce** +Help us figure out what you did to get this issue + +**Screenshots** +If applicable, add screenshots to help explain your problem. + +**Version Information:** + - Minecraft Version: [e.g. 1.20.5] + - Mine Little Pony Version: + +**Mod Loader:** + - [ ] Fabric + - [ ] Quilt + - [ ] Neoforge (with connector) + +**Client/Server Logs** +If applicable, add log files by uploading them as attachments or put them below. + +

+``` +**Paste logs here** +``` +
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 00000000..7b2634da --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,26 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: '' +labels: enhancement +assignees: Sollace + +--- + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Additional context** +Add any other context or screenshots about the feature request here. + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Version Information:** + - Minecraft Version: [e.g. 1.20.5] + - Mine Little Pony Version: + +**Mod Loader:** + - [ ] Fabric + - [ ] Quilt + - [ ] Neoforge (with connector) From 956dbd26b9a1cadacfcfd5f09b89e364b99a1873 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 15:13:47 +0100 Subject: [PATCH 018/110] Fix the displacement spell. Fixes #456 --- .../magic/spell/PlacementControlSpell.java | 55 +++++++++---------- .../magic/spell/effect/DisplacementSpell.java | 34 ++++++++++-- .../unicopia/entity/mob/CastSpellEntity.java | 9 ++- 3 files changed, 62 insertions(+), 36 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java index 9eee830f..339deac6 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java @@ -77,39 +77,38 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel @Override public boolean apply(Caster caster) { - if (delegate == null) { - return false; - } - boolean result = super.apply(caster); - if (result) { - if (dimension.isEmpty()) { - setDimension(caster.asWorld().getRegistryKey()); - } - if (position.isEmpty()) { - setPosition(caster.asEntity().getPos()); - } - if (delegate instanceof PlacementDelegate) { - ((PlacementDelegate)delegate).onPlaced(caster, this); - } - - CastSpellEntity entity = new CastSpellEntity(caster.asWorld(), caster, this); - - Vec3d pos = position.get(); - Vec3d rot = orientation.orElse(Vec3d.ZERO); - - entity.updatePositionAndAngles(pos.x, pos.y, pos.z, (float)rot.y, (float)rot.x); - entity.getWorld().spawnEntity(entity); - - placedEntityId = entity.getUuid(); - } - return result; + return delegate != null && super.apply(caster); } @Override public boolean tick(Caster source, Situation situation) { - if (!source.isClient() && getConnection(source) == null) { - setDead(); + if (!source.isClient()) { + + if (placedEntityId == null) { + if (dimension.isEmpty()) { + setDimension(source.asWorld().getRegistryKey()); + } + if (position.isEmpty()) { + setPosition(source.asEntity().getPos()); + } + System.out.println("Creating placed spell"); + CastSpellEntity entity = new CastSpellEntity(source.asWorld(), source, this); + + Vec3d pos = position.get(); + Vec3d rot = orientation.orElse(Vec3d.ZERO); + + entity.updatePositionAndAngles(pos.x, pos.y, pos.z, (float)rot.y, (float)rot.x); + entity.getWorld().spawnEntity(entity); + + placedEntityId = entity.getUuid(); + setDirty(); + } else { + if (getConnection(source) == null) { + setDead(); + } + } } + return !isDead(); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java index 1afef18f..974da9de 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java @@ -18,13 +18,13 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.util.hit.EntityHitResult; import net.minecraft.util.math.Vec3d; -public class DisplacementSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.EntityHitListener { +public class DisplacementSpell extends AbstractSpell implements HomingSpell, ProjectileDelegate.HitListener { private static final SpellAttribute DAMAGE_TO_TARGET = SpellAttribute.create(SpellAttributeType.DAMAGE_TO_TARGET, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.BLOOD, blood -> blood); static final TooltipFactory TOOLTIP = DAMAGE_TO_TARGET; - private final EntityReference target = new EntityReference<>(); + private final EntityReference target = dataTracker.startTracking(new EntityReference<>()); private int ticks = 10; @@ -34,7 +34,7 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro @Override public Spell prepareForCast(Caster caster, CastingMethod method) { - return toPlaceable(); + return method.isIndirectCause() ? this : toPlaceable(); } @Override @@ -43,14 +43,23 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro originator.asEntity().setGlowing(true); + if (situation == Situation.PROJECTILE) { + return !isDead(); + } + ticks--; if (originator.isClient()) { return !isDead() || ticks >= -10; } - if (ticks == 0) { - target.ifPresent(originator.asWorld(), target -> apply(originator, target)); + if (!originator.isClient()) { + target.ifPresent(originator.asWorld(), target -> { + target.setGlowing(true); + if (ticks == 0) { + apply(originator, target); + } + }); } return ticks >= -10; @@ -58,7 +67,18 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro @Override public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) { - Caster.of(projectile.getMaster()).ifPresent(originator -> apply(originator, hit.getEntity())); + HitListener.super.onImpact(projectile, hit); + Caster.of(projectile.getMaster()).ifPresent(originator -> { + apply(originator, hit.getEntity()); + }); + } + + @Override + public void onImpact(MagicProjectileEntity projectile) { + if (projectile.getMaster() instanceof Entity owner) { + owner.setGlowing(false); + } + target.ifPresent(projectile.asWorld(), e -> e.setGlowing(false)); } private void apply(Caster originator, Entity target) { @@ -107,11 +127,13 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro public void toNBT(NbtCompound compound) { super.toNBT(compound); compound.putInt("ticks", ticks); + compound.put("target", target.toNBT()); } @Override public void fromNBT(NbtCompound compound) { super.fromNBT(compound); ticks = compound.getInt("ticks"); + target.fromNBT(compound.getCompound("target")); } } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java b/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java index fbca955c..34216ea4 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/mob/CastSpellEntity.java @@ -11,6 +11,7 @@ import com.minelittlepony.unicopia.ability.magic.SpellSlots; import com.minelittlepony.unicopia.ability.magic.spell.PlacementControlSpell; import com.minelittlepony.unicopia.ability.magic.spell.Situation; import com.minelittlepony.unicopia.ability.magic.spell.Spell; +import com.minelittlepony.unicopia.ability.magic.spell.PlacementControlSpell.PlacementDelegate; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.EntityPhysics; import com.minelittlepony.unicopia.entity.EntityReference; @@ -70,8 +71,12 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster type, World world) { From 8c560e3ff31ad374b3c3800a804e010f9918049b Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 16:52:44 +0100 Subject: [PATCH 019/110] Fixed amulet rendering when trinkets is not installed. Closes #455 --- build.gradle | 7 ++++++- gradle.properties | 1 + lib/trinkets-dummy-3.8.0.jar | Bin 0 -> 235614 bytes .../compat/trinkets/TrinketsDelegate.java | 2 +- .../unicopia/item/AmuletItem.java | 2 +- 5 files changed, 9 insertions(+), 3 deletions(-) create mode 100644 lib/trinkets-dummy-3.8.0.jar diff --git a/build.gradle b/build.gradle index 8752d140..de730eec 100644 --- a/build.gradle +++ b/build.gradle @@ -78,7 +78,12 @@ dependencies { include "com.sollace:Romanizer:Romanizer:1.0.2" modCompileOnly "com.terraformersmc:modmenu:${project.modmenu_version}" - modCompileOnly "dev.emi:trinkets:${project.trinkets_version}" + + if (project.use_trinkets == '1') { + modCompileOnly "dev.emi:trinkets:${project.trinkets_version}" + } else { + modCompileOnly "dev.emi:trinkets-dummy:${project.trinkets_version}" + } modImplementation "com.terraformersmc.terraform-api:terraform-wood-api-v1:${project.terraformer_api_version}" include "com.terraformersmc.terraform-api:terraform-wood-api-v1:${project.terraformer_api_version}" diff --git a/gradle.properties b/gradle.properties index 7018784c..25ccc1c3 100644 --- a/gradle.properties +++ b/gradle.properties @@ -30,6 +30,7 @@ org.gradle.daemon=false nodium_version=1.1.0+1.20 # Testing + use_trinkets=1 use_pehkui=0 use_sodium=1 diff --git a/lib/trinkets-dummy-3.8.0.jar b/lib/trinkets-dummy-3.8.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..1e65318dcb687edd2e22bddb1464f8f1fb7dba75 GIT binary patch literal 235614 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%0ATS$4NZ{l@p%Kp? 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⋘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

-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 M;eNOzm`UjP6A literal 0 HcmV?d00001 diff --git a/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java b/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java index f19d592a..c73f5d46 100644 --- a/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java +++ b/src/main/java/com/minelittlepony/unicopia/compat/trinkets/TrinketsDelegate.java @@ -127,7 +127,7 @@ public interface TrinketsDelegate { } record EquippedStack(ItemStack stack, Runnable sendUpdate, Consumer breakStatusSender) { - public static EquippedStack EMPTY = new EquippedStack(ItemStack.EMPTY, () -> {}, l -> {}); + public static final EquippedStack EMPTY = new EquippedStack(ItemStack.EMPTY, () -> {}, l -> {}); EquippedStack(LivingEntity entity, EquipmentSlot slot) { this(entity.getEquippedStack(slot), () -> {}, l -> l.sendEquipmentBreakStatus(slot)); diff --git a/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java b/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java index 8e0673f7..a434863f 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/AmuletItem.java @@ -101,7 +101,7 @@ public class AmuletItem extends WearableItem implements ChargeableItem { } public static TrinketsDelegate.EquippedStack get(LivingEntity entity) { - return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE) + return TrinketsDelegate.getInstance(entity).getEquipped(entity, TrinketsDelegate.NECKLACE, stack -> stack.getItem() instanceof AmuletItem) .findFirst() .orElse(TrinketsDelegate.EquippedStack.EMPTY); } From 7b5a7682c4c926cadfb8a47eaae1392310ede00b Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 17:33:13 +0100 Subject: [PATCH 020/110] Fixed bubble spell offset from entity center. Fixes #457 --- .../render/spell/BubbleSpellRenderer.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java index 48f0dbb9..f7fe2241 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/BubbleSpellRenderer.java @@ -19,19 +19,22 @@ public class BubbleSpellRenderer extends SpellRenderer { super.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch); matrices.push(); - double height = caster.asEntity().getEyeY() - caster.getOriginVector().y; - matrices.translate(0, height * 0.5F, 0); + double height = caster.asEntity().getEyeY() - caster.getOriginVector().getY(); - float radius = spell.getRadius(tickDelta) * 0.7F; - VertexConsumer buffer = vertices.getBuffer(RenderLayers.getMagicNoColor()); + float radius = spell.getRadius(tickDelta) * 1.5F; + + matrices.translate(0, radius * 0.5F + height, 0); + + VertexConsumer buffer = vertices.getBuffer(RenderLayers.getMagicShield()); Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity(); matrices.push(); - matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-45)); - matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(45 + cameraEntity.getYaw(tickDelta))); - matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-cameraEntity.getPitch(tickDelta))); + matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90)); + matrices.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(cameraEntity.getYaw(tickDelta) - 25)); + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(-cameraEntity.getPitch(tickDelta))); + new SphereModel(40, 40, DrawableUtil.PI * 0.25F).render(matrices, buffer, light, 0, radius - 0.1F, 0.9F, 0.9F, 1, 0.3F); matrices.pop(); From 2458471fdd0291dca0fa76455212a218312c1eb0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 18:02:59 +0100 Subject: [PATCH 021/110] Fixed rendering wackyness when the timer is displayed for timed spells --- .../client/render/spell/SpellRenderer.java | 26 +++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java index a1171b7c..be29e501 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/spell/SpellRenderer.java @@ -1,5 +1,7 @@ package com.minelittlepony.unicopia.client.render.spell; +import org.joml.Quaternionf; + import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Spell; @@ -13,6 +15,8 @@ import net.minecraft.client.MinecraftClient; import net.minecraft.client.render.VertexConsumerProvider; import net.minecraft.client.render.model.json.ModelTransformationMode; import net.minecraft.client.util.math.MatrixStack; +import net.minecraft.entity.EntityPose; +import net.minecraft.entity.LivingEntity; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RotationAxis; @@ -37,6 +41,8 @@ public class SpellRenderer { private void renderGemstone(MatrixStack matrices, VertexConsumerProvider vertices, T spell, Caster caster, int light, float tickDelta, float animationProgress) { matrices.push(); + float scale = 1/8F; + matrices.scale(scale, scale, scale); transformGemstone(matrices, vertices, spell, caster, animationProgress); matrices.push(); @@ -46,6 +52,22 @@ public class SpellRenderer { matrices.pop(); if (spell instanceof TimedSpell timed) { + if (caster.asEntity() instanceof LivingEntity l && !l.isInPose(EntityPose.SLEEPING)) { + float bodyYaw = MathHelper.lerpAngleDegrees(tickDelta, l.prevBodyYaw, l.bodyYaw); + float headYaw = MathHelper.lerpAngleDegrees(tickDelta, l.prevHeadYaw, l.headYaw); + float yawDifference = headYaw - bodyYaw; + if (l.hasVehicle() && l.getVehicle() instanceof LivingEntity vehicle) { + bodyYaw = MathHelper.lerpAngleDegrees(tickDelta, vehicle.prevBodyYaw, vehicle.bodyYaw); + yawDifference = headYaw - bodyYaw; + float clampedYawDifference = MathHelper.clamp(MathHelper.wrapDegrees(yawDifference), -85, 85); + bodyYaw = headYaw - clampedYawDifference; + if (clampedYawDifference * clampedYawDifference > 2500) { + bodyYaw += clampedYawDifference * 0.2F; + } + yawDifference = headYaw - bodyYaw; + } + matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(180 - bodyYaw)); + } renderCountdown(matrices, timed, tickDelta); } @@ -53,7 +75,7 @@ public class SpellRenderer { } protected void renderCountdown(MatrixStack matrices, TimedSpell spell, float tickDelta) { - matrices.multiply(client.getEntityRenderDispatcher().getRotation().invert()); + matrices.multiply(client.getEntityRenderDispatcher().getRotation().invert(new Quaternionf())); float radius = 0.6F; float timeRemaining = spell.getTimer().getPercentTimeRemaining(tickDelta); @@ -67,6 +89,6 @@ public class SpellRenderer { if (caster.asEntity() instanceof CastSpellEntity) { y = 1F; } - matrices.translate(0, y + MathHelper.sin(animationProgress / 3F) * 0.2F, 0); + matrices.translate(0, y * 8 + MathHelper.sin(animationProgress / 3F) * 0.2F, 0); } } From a3d5670f7ac963fefbd5c30359aaf9f5c567865c Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 18:24:34 +0100 Subject: [PATCH 022/110] Adjust bat pony visibility. Fixes #425 --- .../java/com/minelittlepony/unicopia/entity/player/Pony.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index 9d09beaa..cba9e735 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -597,7 +597,7 @@ public class Pony extends Living implements Copyable, Update float lightScale = light / 15F; float approachFactor = ((velocityScale + lightScale) / 2F); - if (approachFactor < (entity.isSneaking() ? 0.8F : 0.6F)) { + if (approachFactor < (entity.isSneaking() ? 0.8F : 0.3F)) { return false; } } From 55a57c3d1b2f0095328d1946c47878ed659146dc Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 18:35:42 +0100 Subject: [PATCH 023/110] Fix compatibility with Xaero's minimap. Fixes #437 --- src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java index 590ed1e7..687bcffb 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java @@ -84,7 +84,7 @@ public class UHud { Pony pony = Pony.of(client.player); matrices.push(); - matrices.translate(0, 0, hotbarZ); + matrices.translate(0, 0, hotbarZ - 9800); renderViewEffects(pony, context, scaledWidth, scaledHeight, tickDelta); matrices.pop(); From ac1ac5d903078737f65e688b6e846a10027f2b6c Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 18:44:25 +0100 Subject: [PATCH 024/110] Fixed heavy enchant making pegasi faster. Fixes #380 --- .../unicopia/entity/player/PlayerPhysics.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index 6b729dfd..01850b5b 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -377,16 +377,17 @@ public class PlayerPhysics extends EntityPhysics implements Tickab tickGrounded(); } - if (!entity.isOnGround()) { - float heavyness = 1 - EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity) * 0.015F; - velocity.x /= heavyness; - velocity.z /= heavyness; - } - float maximum = 1.5F; velocity.x = MathHelper.clamp(velocity.x, -maximum, maximum); velocity.y = MathHelper.clamp(velocity.y, -maximum, maximum); velocity.z = MathHelper.clamp(velocity.z, -maximum, maximum); + + if (!entity.isOnGround()) { + float heavyness = 1 + EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity) * 0.009F; + velocity.x /= heavyness; + velocity.z /= heavyness; + } + entity.setVelocity(velocity.toImmutable()); if (isFlying() && !entity.isFallFlying() && !pony.getAcrobatics().isHanging() && pony.isClient()) { From 68146c4f8cd0f135db13aa7a49b6327a48a40df0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 22:17:40 +0100 Subject: [PATCH 025/110] Set tribe swap damage type to bypass things that normally block damage. May help with #453 --- .../unicopia/datagen/providers/tag/UDamageTypeProvider.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java index a257ccb4..2c8779f3 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java @@ -35,9 +35,13 @@ public class UDamageTypeProvider extends FabricTagProvider { UDamageTypes.EXHAUSTION, UDamageTypes.GAVITY_WELL_RECOIL, UDamageTypes.ALICORN_AMULET, UDamageTypes.ZAP_APPLE, UDamageTypes.KICK, UDamageTypes.SMASH, UDamageTypes.BAT_SCREECH, UDamageTypes.LOVE_DRAINING, UDamageTypes.LIFE_DRAINING, UDamageTypes.STEAMROLLER, UDamageTypes.RAINBOOM, - UDamageTypes.SUN, UDamageTypes.SUNLIGHT, UDamageTypes.PETRIFIED + UDamageTypes.SUN, UDamageTypes.SUNLIGHT, UDamageTypes.PETRIFIED, UDamageTypes.TRIBE_SWAP ); getOrCreateTagBuilder(DamageTypeTags.BYPASSES_INVULNERABILITY).add(UDamageTypes.TRIBE_SWAP); + getOrCreateTagBuilder(DamageTypeTags.BYPASSES_COOLDOWN).add(UDamageTypes.TRIBE_SWAP); + getOrCreateTagBuilder(DamageTypeTags.BYPASSES_EFFECTS).add(UDamageTypes.TRIBE_SWAP); + getOrCreateTagBuilder(DamageTypeTags.BYPASSES_RESISTANCE).add(UDamageTypes.TRIBE_SWAP); + getOrCreateTagBuilder(DamageTypeTags.BYPASSES_ENCHANTMENTS).add(UDamageTypes.TRIBE_SWAP); getOrCreateTagBuilder(DamageTypeTags.BYPASSES_SHIELD).add( UDamageTypes.EXHAUSTION, UDamageTypes.BAT_SCREECH, UDamageTypes.ALICORN_AMULET, UDamageTypes.LOVE_DRAINING, UDamageTypes.LIFE_DRAINING, From 72615aac95c97053e0ad432e5da4f09a28e09072 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 22:19:52 +0100 Subject: [PATCH 026/110] Sunglasses can now be broken by a warden's sonic boom, falling blocks, anvils, explosions, and flying into walls. Closes #423 --- .../datagen/providers/tag/UDamageTypeProvider.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java index 2c8779f3..1506283c 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java @@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.entity.damage.UDamageTypes; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider; import net.minecraft.entity.damage.DamageType; +import net.minecraft.entity.damage.DamageTypes; import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.RegistryWrapper.WrapperLookup; import net.minecraft.registry.tag.DamageTypeTags; @@ -25,7 +26,11 @@ public class UDamageTypeProvider extends FabricTagProvider { ).forceAddTag(DamageTypeTags.IS_FALL).forceAddTag(DamageTypeTags.IS_FREEZING).forceAddTag(DamageTypeTags.IS_LIGHTNING).forceAddTag(DamageTypeTags.IS_PROJECTILE); getOrCreateTagBuilder(UTags.DamageTypes.FROM_ROCKS).add(UDamageTypes.ROCK); getOrCreateTagBuilder(UTags.DamageTypes.FROM_HORSESHOES).add(UDamageTypes.HORSESHOE); - getOrCreateTagBuilder(UTags.DamageTypes.BREAKS_SUNGLASSES).add(UDamageTypes.BAT_SCREECH, UDamageTypes.RAINBOOM); + getOrCreateTagBuilder(UTags.DamageTypes.BREAKS_SUNGLASSES).add( + UDamageTypes.BAT_SCREECH, UDamageTypes.RAINBOOM, + DamageTypes.FLY_INTO_WALL, DamageTypes.FALLING_ANVIL, DamageTypes.FALLING_BLOCK, + DamageTypes.SONIC_BOOM + ).forceAddTag(DamageTypeTags.IS_EXPLOSION); getOrCreateTagBuilder(DamageTypeTags.AVOIDS_GUARDIAN_THORNS).add( UDamageTypes.EXHAUSTION, UDamageTypes.ALICORN_AMULET, UDamageTypes.ZAP_APPLE, UDamageTypes.KICK, UDamageTypes.SMASH, From 3f9d26f4b491ffc839a34c860a00aeb942028253 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 22:35:45 +0100 Subject: [PATCH 027/110] Why is gradle's compiler so stupid? Can ANYONE tell me why gradle's compiler is so stupid!? --- .../ability/magic/spell/effect/DisplacementSpell.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java index 974da9de..d9659de6 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java @@ -75,8 +75,8 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro @Override public void onImpact(MagicProjectileEntity projectile) { - if (projectile.getMaster() instanceof Entity owner) { - owner.setGlowing(false); + if (projectile.getMaster() != null) { + projectile.getMaster().setGlowing(false); } target.ifPresent(projectile.asWorld(), e -> e.setGlowing(false)); } From 37a7b08e45e7901c29a95d7257eb78935a96e381 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 18 Sep 2024 22:51:06 +0100 Subject: [PATCH 028/110] Add support for serene seasons. Closes #386 --- .../providers/tag/SereneSeasonsTags.java | 32 +++++++++++++++++++ .../providers/tag/UBlockTagProvider.java | 25 +++++++++++++++ .../providers/tag/UItemTagProvider.java | 5 +++ 3 files changed, 62 insertions(+) create mode 100644 src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/SereneSeasonsTags.java diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/SereneSeasonsTags.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/SereneSeasonsTags.java new file mode 100644 index 00000000..100dcc99 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/SereneSeasonsTags.java @@ -0,0 +1,32 @@ +package com.minelittlepony.unicopia.datagen.providers.tag; + +import net.minecraft.block.Block; +import net.minecraft.item.Item; +import net.minecraft.registry.RegistryKeys; +import net.minecraft.registry.tag.TagKey; +import net.minecraft.util.Identifier; + +public interface SereneSeasonsTags { + interface Items { + TagKey AUTUMN_CROPS = item("autumn_crops"); + TagKey WINTER_CROPS = item("winter_crops"); + TagKey SPRING_CROPS = item("spring_crops"); + TagKey SUMMER_CROPS = item("summer_crops"); + + private static TagKey item(String name) { + return TagKey.of(RegistryKeys.ITEM, new Identifier("sereneseasons", name)); + } + } + + interface Blocks { + TagKey AUTUMN_CROPS = block("autumn_crops"); + TagKey WINTER_CROPS = block("winter_crops"); + TagKey SPRING_CROPS = block("spring_crops"); + TagKey SUMMER_CROPS = block("summer_crops"); + + private static TagKey block(String name) { + return TagKey.of(RegistryKeys.BLOCK, new Identifier("sereneseasons", name)); + } + } + +} diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UBlockTagProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UBlockTagProvider.java index 66ea54f0..b741612e 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UBlockTagProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UBlockTagProvider.java @@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.block.UBlocks; import com.minelittlepony.unicopia.server.world.Tree; +import com.minelittlepony.unicopia.server.world.UTreeGen; import net.fabricmc.fabric.api.datagen.v1.FabricDataOutput; import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider; @@ -103,6 +104,30 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider { ).forceAddTag(TagKey.of(RegistryKeys.BLOCK, new Identifier("c", "concrete_powders"))); getOrCreateTagBuilder(UTags.Blocks.UNAFFECTED_BY_GROW_ABILITY).add(Blocks.GRASS_BLOCK); + addSeasonalCrops(); + } + + private void addSeasonalCrops() { + getOrCreateTagBuilder(SereneSeasonsTags.Blocks.AUTUMN_CROPS).add( + UBlocks.GREEN_APPLE_LEAVES, UBlocks.GREEN_APPLE_SPROUT, UTreeGen.GREEN_APPLE_TREE.sapling().get(), + UBlocks.SOUR_APPLE_LEAVES, UBlocks.SOUR_APPLE_SPROUT, UTreeGen.SOUR_APPLE_TREE.sapling().get(), + UBlocks.OATS_CROWN, UBlocks.OATS_STEM, UBlocks.OATS, + UBlocks.ROCKS + ); + getOrCreateTagBuilder(SereneSeasonsTags.Blocks.WINTER_CROPS).add(UBlocks.ROCKS); + getOrCreateTagBuilder(SereneSeasonsTags.Blocks.SPRING_CROPS).add( + UBlocks.SWEET_APPLE_LEAVES, UBlocks.SWEET_APPLE_SPROUT, UTreeGen.SWEET_APPLE_TREE.sapling().get(), + UBlocks.GOLDEN_OAK_LEAVES, UBlocks.GOLDEN_OAK_SPROUT, UTreeGen.GOLDEN_APPLE_TREE.sapling().get(), + UBlocks.PALM_LEAVES, UBlocks.BANANAS, UTreeGen.BANANA_TREE.sapling().get(), + UBlocks.PINEAPPLE, + UBlocks.ROCKS + ); + getOrCreateTagBuilder(SereneSeasonsTags.Blocks.SUMMER_CROPS).add( + UBlocks.SWEET_APPLE_LEAVES, UBlocks.SWEET_APPLE_SPROUT, UTreeGen.SWEET_APPLE_TREE.sapling().get(), + UBlocks.MANGO_LEAVES, UTreeGen.MANGO_TREE.sapling().get(), + UBlocks.OATS_CROWN, UBlocks.OATS_STEM, UBlocks.OATS, + UBlocks.ROCKS + ); } private void addFruitTrees() { diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java index 44d1db03..9e579480 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java @@ -175,6 +175,11 @@ public class UItemTagProvider extends FabricTagProvider.ItemTagProvider { copy(UTags.Blocks.CLOUD_STAIRS, UTags.Items.CLOUD_STAIRS); copy(UTags.Blocks.CLOUD_BLOCKS, UTags.Items.CLOUD_BLOCKS); copy(UTags.Blocks.CHITIN_BLOCKS, UTags.Items.CHITIN_BLOCKS); + + copy(SereneSeasonsTags.Blocks.AUTUMN_CROPS, SereneSeasonsTags.Items.AUTUMN_CROPS); + copy(SereneSeasonsTags.Blocks.WINTER_CROPS, SereneSeasonsTags.Items.WINTER_CROPS); + copy(SereneSeasonsTags.Blocks.SPRING_CROPS, SereneSeasonsTags.Items.SPRING_CROPS); + copy(SereneSeasonsTags.Blocks.SUMMER_CROPS, SereneSeasonsTags.Items.SUMMER_CROPS); } private void exportForagingTags() { From 2016b7dd84845d5947756bc9d38209a3226ef890 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 19 Sep 2024 21:24:28 +0100 Subject: [PATCH 029/110] Fixed spells not executing their on destroy handlers --- .../minelittlepony/unicopia/ability/magic/MultiSpellSlot.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java index e38184b7..5a1d9788 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java @@ -114,8 +114,10 @@ class MultiSpellSlot implements SpellSlots, NbtSerialisable { } else { Spell s = spell.get(); if (s != null) { - s.setDead(); s.tickDying(owner); + if (s.isDead()) { + s.destroy(owner); + } } } } From dc3367806255f38f65ff7f61cd4f47f2257fb4aa Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 19 Sep 2024 21:25:29 +0100 Subject: [PATCH 030/110] Fix background rendering in the dismiss spell screen --- .../unicopia/client/gui/DismissSpellScreen.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java index cddf13b9..23b90dc6 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java @@ -101,6 +101,11 @@ public class DismissSpellScreen extends GameGui { matrices.pop(); } + @Override + public void renderInGameBackground(DrawContext context) { + + } + @Override public boolean shouldPause() { return false; From 420f78eaaf9ec7806da010f7f46701f224e5fa61 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 19 Sep 2024 21:27:53 +0100 Subject: [PATCH 031/110] Track which spells are active on which blocks to make tile-by-tile interactions easier. Requireed by #412 --- .../com/minelittlepony/unicopia/Unicopia.java | 2 + .../unicopia/server/world/Ether.java | 59 +++++++++++-- .../unicopia/server/world/WorldOverlay.java | 2 +- .../unicopia/server/world/chunk/Chunk.java | 64 +++++++++++++++ .../server/world/chunk/PositionalDataMap.java | 63 ++++++++++++++ .../unicopia/server/world/chunk/Section.java | 82 +++++++++++++++++++ 6 files changed, 264 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/chunk/Section.java diff --git a/src/main/java/com/minelittlepony/unicopia/Unicopia.java b/src/main/java/com/minelittlepony/unicopia/Unicopia.java index 8142560d..a6057f85 100644 --- a/src/main/java/com/minelittlepony/unicopia/Unicopia.java +++ b/src/main/java/com/minelittlepony/unicopia/Unicopia.java @@ -31,6 +31,7 @@ import com.minelittlepony.unicopia.item.enchantment.UEnchantments; import com.minelittlepony.unicopia.network.Channel; import com.minelittlepony.unicopia.particle.UParticles; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; +import com.minelittlepony.unicopia.server.world.Ether; import com.minelittlepony.unicopia.server.world.NocturnalSleepManager; import com.minelittlepony.unicopia.server.world.UGameRules; import com.minelittlepony.unicopia.server.world.UWorldGen; @@ -71,6 +72,7 @@ public class Unicopia implements ModInitializer { ((BlockDestructionManager.Source)w).getDestructionManager().tick(); ZapAppleStageStore.get(w).tick(); WeatherConditions.get(w).tick(); + Ether.get(w).tick(); if (Debug.SPELLBOOK_CHAPTERS) { SpellbookChapterLoader.INSTANCE.sendUpdate(w.getServer()); } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java b/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java index 840e66fa..08c6a9a2 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/Ether.java @@ -13,14 +13,18 @@ import com.minelittlepony.unicopia.ability.magic.Caster; import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.EntityReference; +import com.minelittlepony.unicopia.server.world.chunk.PositionalDataMap; import com.minelittlepony.unicopia.util.NbtSerialisable; +import com.minelittlepony.unicopia.util.Tickable; + import net.minecraft.nbt.*; import net.minecraft.util.Identifier; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.world.PersistentState; import net.minecraft.world.World; -public class Ether extends PersistentState { +public class Ether extends PersistentState implements Tickable { private static final Identifier ID = Unicopia.id("ether"); public static Ether get(World world) { @@ -28,6 +32,7 @@ public class Ether extends PersistentState { } private final Map>>> endpoints; + private final PositionalDataMap> positionData = new PositionalDataMap<>(); private final Object locker = new Object(); @@ -70,23 +75,36 @@ public class Ether extends PersistentState { markDirty(); return new Entry<>(spell, caster); }); - if (entry.removed) { - entry.removed = false; - markDirty(); - } + if (entry.spell.get() != spell) { entry.spell = new WeakReference<>(spell); markDirty(); } + if (entry.removed) { + entry.removed = false; + positionData.update(entry); + markDirty(); + } return entry; } } + @Override + public void tick() { + endpoints.values().forEach(byType -> { + byType.values().forEach(entries -> { + entries.values().forEach(Entry::update); + }); + }); + } + public void remove(SpellType spellType, UUID entityId) { synchronized (locker) { endpoints.computeIfPresent(spellType.getId(), (typeId, entries) -> { - if (entries.remove(entityId) != null) { + Map> data = entries.remove(entityId); + if (data != null) { markDirty(); + data.values().forEach(positionData::remove); } return entries.isEmpty() ? null : entries; }); @@ -150,6 +168,10 @@ public class Ether extends PersistentState { return false; } + public Set> getAtPosition(BlockPos pos) { + return world.isClient() ? Set.of() : positionData.getState(pos); + } + private void pruneNodes() { this.endpoints.values().removeIf(entities -> { entities.values().removeIf(spells -> { @@ -160,7 +182,7 @@ public class Ether extends PersistentState { }); } - public class Entry implements NbtSerialisable { + public class Entry implements PositionalDataMap.Hotspot, NbtSerialisable { public final EntityReference entity; @Nullable @@ -176,6 +198,9 @@ public class Ether extends PersistentState { private final Set claimants = new HashSet<>(); + private BlockPos currentPos = BlockPos.ORIGIN; + private BlockPos previousPos = BlockPos.ORIGIN; + private Entry(NbtElement nbt) { this.entity = new EntityReference<>(); this.spell = new WeakReference<>(null); @@ -186,6 +211,15 @@ public class Ether extends PersistentState { this.entity = new EntityReference<>(caster.asEntity()); this.spell = new WeakReference<>(spell); spellId = spell.getUuid(); + update(); + } + + void update() { + previousPos = currentPos; + currentPos = entity.getTarget().map(t -> BlockPos.ofFloored(t.pos())).orElse(BlockPos.ORIGIN); + if (!currentPos.equals(previousPos)) { + positionData.update(this); + } } public boolean hasChanged() { @@ -216,6 +250,13 @@ public class Ether extends PersistentState { markDirty(); } + + @Override + public BlockPos getCenter() { + return currentPos; + } + + @Override public float getRadius() { return radius; } @@ -223,6 +264,9 @@ public class Ether extends PersistentState { public void setRadius(float radius) { if (!MathHelper.approximatelyEquals(this.radius, radius)) { this.radius = radius; + if ((int)radius != (int)this.radius) { + positionData.update(this); + } changed.set(true); } markDirty(); @@ -247,6 +291,7 @@ public class Ether extends PersistentState { public void markDead() { Unicopia.LOGGER.debug("Marking " + entity.getTarget().orElse(null) + " as dead"); removed = true; + positionData.remove(this); claimants.clear(); markDirty(); } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/WorldOverlay.java b/src/main/java/com/minelittlepony/unicopia/server/world/WorldOverlay.java index 8d4512b4..4c5212a9 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/WorldOverlay.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/WorldOverlay.java @@ -94,7 +94,7 @@ public class WorldOverlay extends PersistentState } private Chunk getChunk(BlockPos pos) { - return chunks.computeIfAbsent(new ChunkPos(pos).toLong(), Chunk::new); + return chunks.computeIfAbsent(ChunkPos.toLong(pos), Chunk::new); } public void setState(BlockPos pos, @Nullable T state) { diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java new file mode 100644 index 00000000..d59919db --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Chunk.java @@ -0,0 +1,64 @@ +package com.minelittlepony.unicopia.server.world.chunk; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.ChunkSectionPos; + +public class Chunk { + private final Long2ObjectMap> sections = new Long2ObjectOpenHashMap<>(); + private final Map>> entryToSections = new WeakHashMap<>(); + + Chunk(long pos) { } + + public synchronized Set getState(BlockPos pos) { + Section section = sections.get(ChunkSectionPos.getSectionCoord(pos.getY())); + return section == null ? Set.of() : section.getState(pos); + } + + public synchronized boolean remove(T entry) { + Set> sections = entryToSections.remove(entry); + if (sections != null) { + sections.forEach(section -> { + if (section.remove(entry) && section.isEmpty()) { + this.sections.remove(section.pos); + } + }); + return true; + } + return false; + } + + public synchronized boolean update(T entry, Box entryBox) { + Set> oldSections = entryToSections.get(entry); + Set> newSections = getIntersectingSections(entryBox); + if (oldSections != null) { + oldSections.forEach(section -> { + if (!newSections.contains(section) && section.remove(entry) && section.isEmpty()) { + this.sections.remove(section.pos); + } + }); + } + newSections.forEach(chunk -> chunk.update(entry, entryBox)); + entryToSections.put(entry, newSections); + return true; + } + + private Set> getIntersectingSections(Box entryBox) { + Set> sections = new HashSet<>(); + + int minY = ChunkSectionPos.getSectionCoord(entryBox.minY); + int maxY = ChunkSectionPos.getSectionCoord(entryBox.maxY); + for (int y = minY; y <= maxY; y++) { + sections.add(this.sections.computeIfAbsent(y, Section::new)); + } + + return sections; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java new file mode 100644 index 00000000..eb2ee335 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/PositionalDataMap.java @@ -0,0 +1,63 @@ +package com.minelittlepony.unicopia.server.world.chunk; + +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.WeakHashMap; + +import it.unimi.dsi.fastutil.longs.Long2ObjectMap; +import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.ChunkSectionPos; +import net.minecraft.util.math.MathHelper; + +public class PositionalDataMap { + private final Long2ObjectMap> chunks = new Long2ObjectOpenHashMap<>(); + private final Map>> entryToChunks = new WeakHashMap<>(); + + public Set getState(BlockPos pos) { + Chunk chunk = chunks.get(ChunkPos.toLong(pos)); + return chunk == null ? Set.of() : chunk.getState(pos); + } + + public void remove(T entry) { + Set> chunks = entryToChunks.remove(entry); + if (chunks != null) { + chunks.forEach(chunk -> chunk.remove(entry)); + } + } + + public void update(T entry) { + Box entryBox = new Box(entry.getCenter()).expand(MathHelper.ceil(entry.getRadius())); + Set> oldChunks = entryToChunks.get(entry); + Set> newChunks = getIntersectingChunks(entryBox); + if (oldChunks != null) { + oldChunks.forEach(chunk -> chunk.remove(entry)); + } + newChunks.forEach(chunk -> chunk.update(entry, entryBox)); + entryToChunks.put(entry, newChunks); + } + + private Set> getIntersectingChunks(Box entryBox) { + int minX = ChunkSectionPos.getSectionCoord(entryBox.minX); + int maxX = ChunkSectionPos.getSectionCoord(entryBox.maxX); + int minZ = ChunkSectionPos.getSectionCoord(entryBox.minZ); + int maxZ = ChunkSectionPos.getSectionCoord(entryBox.maxZ); + + Set> chunks = new HashSet<>(); + for (int x = minX; x <= maxX; x++) { + for (int z = minZ; z <= maxZ; z++) { + chunks.add(this.chunks.computeIfAbsent(ChunkPos.toLong(x, z), Chunk::new)); + } + } + return chunks; + } + + public interface Hotspot { + float getRadius(); + + BlockPos getCenter(); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Section.java b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Section.java new file mode 100644 index 00000000..7024acdc --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/chunk/Section.java @@ -0,0 +1,82 @@ +package com.minelittlepony.unicopia.server.world.chunk; + +import java.util.Collections; +import java.util.Set; +import java.util.WeakHashMap; + +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Box; +import net.minecraft.util.math.MathHelper; + +public class Section { + private final Set entries = weakSet(); + private Set[] states; + + final long pos; + + public Section(long pos) { + this.pos = pos; + } + + public boolean isEmpty() { + return entries.isEmpty(); + } + + public boolean remove(T entry) { + if (entries.remove(entry)) { + states = null; + return true; + } + return false; + } + + public boolean update(T entry, Box box) { + entries.add(entry); + states = null; + return true; + } + + @SuppressWarnings("unchecked") + public Set getState(BlockPos pos) { + int localPos = toLocalIndex(pos); + if (states == null) { + states = new Set[16 * 16 * 16]; + } + Set state = states[localPos]; + return state == null ? (states[localPos] = calculateState(pos)) : state; + } + + private Set calculateState(BlockPos pos) { + Set state = weakSet(); + + for (T entry : entries) { + BlockPos center = entry.getCenter(); + int radius = MathHelper.ceil(entry.getRadius()); + + if (pos.equals(center) + || (isInRange(pos.getX(), center.getX(), radius) + && isInRange(pos.getZ(), center.getZ(), radius) + && isInRange(pos.getY(), center.getY(), radius) + && center.isWithinDistance(pos, radius))) { + state.add(entry); + } + } + + return state; + } + + static boolean isInRange(int value, int center, int radius) { + return value >= center - radius && value <= center + radius; + } + + static int toLocalIndex(BlockPos pos) { + int x = pos.getX() % 16; + int y = pos.getY() % 16; + int z = pos.getZ() % 16; + return x + (y * 16) + (z * 16 * 16); + } + + static Set weakSet() { + return Collections.newSetFromMap(new WeakHashMap<>()); + } +} From 92ad502fa7f8db0efb218876f7a568777a788e22 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 19 Sep 2024 23:26:23 +0100 Subject: [PATCH 032/110] Set the spell as dead when removing it --- .../minelittlepony/unicopia/ability/magic/MultiSpellSlot.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java index 5a1d9788..816047c9 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java @@ -114,6 +114,7 @@ class MultiSpellSlot implements SpellSlots, NbtSerialisable { } else { Spell s = spell.get(); if (s != null) { + s.setDead(); s.tickDying(owner); if (s.isDead()) { s.destroy(owner); From 469aaeecd1612691d2841e1faee718a9606c1b83 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 21 Sep 2024 21:40:20 +0100 Subject: [PATCH 033/110] Remove Spell#isDirty and Spell#setDirty --- .../ability/magic/MultiSpellSlot.java | 2 +- .../magic/spell/AbstractDelegatingSpell.java | 12 ---- .../magic/spell/AbstractDisguiseSpell.java | 2 +- .../ability/magic/spell/EmptySpell.java | 8 --- .../magic/spell/PlacementControlSpell.java | 64 +++++++++---------- .../unicopia/ability/magic/spell/Spell.java | 12 ---- .../ability/magic/spell/SpellReference.java | 5 -- .../magic/spell/effect/AbstractSpell.java | 14 ---- .../magic/spell/effect/AttractiveSpell.java | 6 +- .../magic/spell/effect/AwkwardSpell.java | 3 +- .../magic/spell/effect/BubbleSpell.java | 9 +-- .../magic/spell/effect/FeatherFallSpell.java | 3 +- .../magic/spell/effect/FireBoltSpell.java | 2 +- .../magic/spell/effect/LightSpell.java | 3 +- .../magic/spell/effect/MimicSpell.java | 3 +- .../magic/spell/effect/PortalSpell.java | 2 +- .../render/EntityReplacementManager.java | 4 -- .../unicopia/entity/behaviour/Disguise.java | 3 - .../entity/behaviour/EntityAppearance.java | 46 ++++++++++++- .../entity/behaviour/SheepBehaviour.java | 2 +- .../network/track/TrackableDataType.java | 10 +++ .../util/serialization/PacketCodec.java | 17 ++++- 22 files changed, 114 insertions(+), 118 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java index 816047c9..50cb5902 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java @@ -131,7 +131,7 @@ class MultiSpellSlot implements SpellSlots, NbtSerialisable { return hasValue ? Status.NEW : Status.REMOVED; } - return spell.hasDirtySpell() ? Status.UPDATED : Status.DEFAULT; + return Status.DEFAULT; } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java index 78373b5a..9ff86367 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDelegatingSpell.java @@ -80,18 +80,6 @@ public abstract class AbstractDelegatingSpell implements Spell { return getOrEmpty().isDying(); } - @Deprecated - @Override - public boolean isDirty() { - return delegate.hasDirtySpell(); - } - - @Deprecated - @Override - public void setDirty() { - getOrEmpty().setDirty(); - } - @Override public boolean isHidden() { return getOrEmpty().isHidden(); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDisguiseSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDisguiseSpell.java index 41e7c996..b4e6ad08 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDisguiseSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/AbstractDisguiseSpell.java @@ -20,7 +20,7 @@ import net.minecraft.nbt.NbtCompound; */ public abstract class AbstractDisguiseSpell extends AbstractSpell implements Disguise, ProjectileImpactListener { - private final EntityAppearance disguise = new EntityAppearance(); + private final EntityAppearance disguise = dataTracker.startTracking(new EntityAppearance()); public AbstractDisguiseSpell(CustomisedSpellType type) { super(type); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/EmptySpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/EmptySpell.java index 89b3f986..f4dca074 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/EmptySpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/EmptySpell.java @@ -44,11 +44,6 @@ public final class EmptySpell implements Spell { return false; } - @Override - public boolean isDirty() { - return false; - } - @Override public boolean tick(Caster caster, Situation situation) { return false; @@ -57,9 +52,6 @@ public final class EmptySpell implements Spell { @Override public void tickDying(Caster caster) { } - @Override - public void setDirty() { } - @Override public boolean isHidden() { return true; diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java index 339deac6..e3f31a03 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/PlacementControlSpell.java @@ -9,6 +9,8 @@ import com.minelittlepony.unicopia.ability.magic.spell.effect.AbstractSpell; import com.minelittlepony.unicopia.ability.magic.spell.effect.CustomisedSpellType; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.mob.CastSpellEntity; +import com.minelittlepony.unicopia.network.track.DataTracker; +import com.minelittlepony.unicopia.network.track.TrackableDataType; import com.minelittlepony.unicopia.server.world.Ether; import com.minelittlepony.unicopia.util.NbtSerialisable; @@ -21,12 +23,10 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; public class PlacementControlSpell extends AbstractSpell implements OrientedSpell { - @Nullable - private UUID placedEntityId; - - private Optional> dimension = Optional.empty(); - private Optional position = Optional.empty(); - private Optional orientation = Optional.empty(); + private final DataTracker.Entry placedEntityId = dataTracker.startTracking(TrackableDataType.UUID, null); + private final DataTracker.Entry>> dimension = dataTracker.startTracking(TrackableDataType.ofRegistryKey(), Optional.empty()); + private final DataTracker.Entry> position = dataTracker.startTracking(TrackableDataType.OPTIONAL_VECTOR, Optional.empty()); + private final DataTracker.Entry> orientation = dataTracker.startTracking(TrackableDataType.OPTIONAL_VECTOR, Optional.empty()); @Nullable private Spell delegate; @@ -46,26 +46,23 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel } public Optional getPosition() { - return position; + return position.get(); } public void setDimension(RegistryKey dimension) { - this.dimension = Optional.of(dimension); - setDirty(); + this.dimension.set(Optional.of(dimension)); } public void setPosition(Vec3d position) { - this.position = Optional.of(position); - setDirty(); + this.position.set(Optional.of(position)); } @Override public void setOrientation(Caster caster, float pitch, float yaw) { - this.orientation = Optional.of(new Vec3d(pitch, yaw, 0)); + this.orientation.set(Optional.of(new Vec3d(pitch, yaw, 0))); if (delegate instanceof OrientedSpell o) { o.setOrientation(caster, pitch, yaw); } - setDirty(); if (!caster.isClient()) { var entry = getConnection(caster); if (entry != null) { @@ -84,24 +81,23 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel public boolean tick(Caster source, Situation situation) { if (!source.isClient()) { - if (placedEntityId == null) { - if (dimension.isEmpty()) { + if (placedEntityId.get() == null) { + if (dimension.get().isEmpty()) { setDimension(source.asWorld().getRegistryKey()); } - if (position.isEmpty()) { + if (getPosition().isEmpty()) { setPosition(source.asEntity().getPos()); } - System.out.println("Creating placed spell"); + CastSpellEntity entity = new CastSpellEntity(source.asWorld(), source, this); - Vec3d pos = position.get(); - Vec3d rot = orientation.orElse(Vec3d.ZERO); + Vec3d pos = getPosition().get(); + Vec3d rot = orientation.get().orElse(Vec3d.ZERO); entity.updatePositionAndAngles(pos.x, pos.y, pos.z, (float)rot.y, (float)rot.x); entity.getWorld().spawnEntity(entity); - placedEntityId = entity.getUuid(); - setDirty(); + placedEntityId.set(entity.getUuid()); } else { if (getConnection(source) == null) { setDead(); @@ -114,24 +110,24 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel @Nullable private Ether.Entry getConnection(Caster source) { - return delegate == null || placedEntityId == null ? null : getWorld(source) - .map(world -> Ether.get(world).get(getDelegate().getTypeAndTraits().type(), placedEntityId, delegate.getUuid())) + return delegate == null || placedEntityId.get() == null ? null : getWorld(source) + .map(world -> Ether.get(world).get(getDelegate().getTypeAndTraits().type(), placedEntityId.get(), delegate.getUuid())) .orElse(null); } private Optional getWorld(Caster source) { - return dimension.map(source.asWorld().getServer()::getWorld); + return dimension.get().map(source.asWorld().getServer()::getWorld); } @Override public void toNBT(NbtCompound compound) { super.toNBT(compound); compound.put("spell", Spell.writeNbt(delegate)); - position.ifPresent(pos -> compound.put("position", NbtSerialisable.writeVector(pos))); - orientation.ifPresent(o -> compound.put("orientation", NbtSerialisable.writeVector(o))); - dimension.ifPresent(d -> compound.putString("dimension", d.getValue().toString())); - if (placedEntityId != null) { - compound.putUuid("placedEntityId", placedEntityId); + position.get().ifPresent(pos -> compound.put("position", NbtSerialisable.writeVector(pos))); + orientation.get().ifPresent(o -> compound.put("orientation", NbtSerialisable.writeVector(o))); + dimension.get().ifPresent(d -> compound.putString("dimension", d.getValue().toString())); + if (placedEntityId.get() != null) { + compound.putUuid("placedEntityId", placedEntityId.get()); } } @@ -139,12 +135,10 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel public void fromNBT(NbtCompound compound) { super.fromNBT(compound); delegate = Spell.readNbt(compound.getCompound("spell")); - placedEntityId = compound.containsUuid("placedEntityId") ? compound.getUuid("placedEntityId") : null; - position = compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.DOUBLE_TYPE))) : Optional.empty(); - orientation = compound.contains("orientation") ? Optional.of(NbtSerialisable.readVector(compound.getList("orientation", NbtElement.DOUBLE_TYPE))) : Optional.empty(); - if (compound.contains("dimension", NbtElement.STRING_TYPE)) { - dimension = Optional.ofNullable(Identifier.tryParse(compound.getString("dimension"))).map(id -> RegistryKey.of(RegistryKeys.WORLD, id)); - } + placedEntityId.set(compound.containsUuid("placedEntityId") ? compound.getUuid("placedEntityId") : null); + position.set(compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.DOUBLE_TYPE))) : Optional.empty()); + orientation.set(compound.contains("orientation") ? Optional.of(NbtSerialisable.readVector(compound.getList("orientation", NbtElement.DOUBLE_TYPE))) : Optional.empty()); + dimension.set(compound.contains("dimension", NbtElement.STRING_TYPE) ? Optional.ofNullable(Identifier.tryParse(compound.getString("dimension"))).map(id -> RegistryKey.of(RegistryKeys.WORLD, id)) : Optional.empty()); } public interface PlacementDelegate { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java index aab10703..6add4b0f 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/Spell.java @@ -74,18 +74,6 @@ public interface Spell extends NbtSerialisable, Affine { boolean isDying(); - /** - * Returns true if this effect has changes that need to be sent to the client. - */ - @Deprecated - boolean isDirty(); - - /** - * Marks this effect as dirty. - */ - @Deprecated - void setDirty(); - /** * Applies this spell to the supplied caster. * @param caster The caster to apply the spell to diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java index 4bab564c..66cd3acc 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/SpellReference.java @@ -25,11 +25,6 @@ public final class SpellReference implements NbtSerialisable { set(spell, null); } - @Deprecated - public boolean hasDirtySpell() { - return spell != null && spell.isDirty(); - } - public boolean set(T spell, @Nullable Caster owner) { spell = spell == null || spell.isDead() ? null : spell; if (spell == this.spell) { diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java index 6d08d6a9..16839123 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AbstractSpell.java @@ -20,7 +20,6 @@ public abstract class AbstractSpell implements Spell { private final DataTracker.Entry dead = dataTracker.startTracking(TrackableDataType.BOOLEAN, false); private final DataTracker.Entry dying = dataTracker.startTracking(TrackableDataType.BOOLEAN, false); - private boolean dirty; private final DataTracker.Entry hidden = dataTracker.startTracking(TrackableDataType.BOOLEAN, false); private boolean destroyed; @@ -66,18 +65,6 @@ public abstract class AbstractSpell implements Spell { return dying.get(); } - @Deprecated - @Override - public final boolean isDirty() { - return dirty; - } - - @Deprecated - @Override - public final void setDirty() { - dirty = true; - } - @Override public final boolean isHidden() { return hidden.get(); @@ -120,7 +107,6 @@ public abstract class AbstractSpell implements Spell { @Override public void fromNBT(NbtCompound compound) { - dirty = false; if (compound.containsUuid("uuid")) { uuid = compound.getUuid("uuid"); } diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java index 7bf39425..08b6e1a2 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AttractiveSpell.java @@ -28,14 +28,12 @@ public class AttractiveSpell extends ShieldSpell implements HomingSpell, TimedSp static final TooltipFactory TARGET = (type, tooltip) -> (TARGET_FOCUSED_ENTITY.get(type.traits()) ? TARGET_FOCUSED_ENTITY : ShieldSpell.TARGET).appendTooltip(type, tooltip); static final TooltipFactory TOOLTIP = TooltipFactory.of(TIME, RANGE, TARGET, STICK_TO_TARGET, CAST_ON); - private final EntityReference target = new EntityReference<>(); + private final EntityReference target = dataTracker.startTracking(new EntityReference<>()); - private final Timer timer; + private final Timer timer = new Timer(TIME.get(getTraits())); protected AttractiveSpell(CustomisedSpellType type) { super(type); - timer = new Timer(TIME.get(getTraits())); - dataTracker.startTracking(target); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java index dab51b1b..7a9402c5 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/AwkwardSpell.java @@ -19,11 +19,10 @@ import net.minecraft.registry.Registries; public class AwkwardSpell extends AbstractSpell implements TimedSpell { - private final Timer timer; + private final Timer timer = new Timer(20); protected AwkwardSpell(CustomisedSpellType type) { super(type); - timer = new Timer(20); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java index df1e9c92..dfd6d601 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/BubbleSpell.java @@ -56,17 +56,14 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell, static final TooltipFactory TOOLTIP = TooltipFactory.of(TimedSpell.TIME, SOAPINESS); - private final Timer timer; + private final Timer timer = new Timer(TIME.get(getTraits())); private float prevRadius; - private DataTracker.Entry radius; - private DataTracker.Entry struggles; + private DataTracker.Entry radius = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); + private DataTracker.Entry struggles = dataTracker.startTracking(TrackableDataType.INT, SOAPINESS.get(getTraits())); protected BubbleSpell(CustomisedSpellType type) { super(type); - timer = new Timer(TIME.get(getTraits())); - radius = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); - struggles = dataTracker.startTracking(TrackableDataType.INT, SOAPINESS.get(getTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FeatherFallSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FeatherFallSpell.java index e90558d0..8f7ffabf 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FeatherFallSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FeatherFallSpell.java @@ -59,11 +59,10 @@ public class FeatherFallSpell extends AbstractSpell implements TimedSpell { .with(Trait.ORDER, 15) .build(); - private final Timer timer; + private final Timer timer = new Timer(DURATION.get(getTraits())); protected FeatherFallSpell(CustomisedSpellType type) { super(type); - timer = new Timer(DURATION.get(getTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java index 9075457a..04cf61fd 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/FireBoltSpell.java @@ -47,7 +47,7 @@ public class FireBoltSpell extends AbstractSpell implements HomingSpell, static final TooltipFactory TOOLTIP = TooltipFactory.of(EXPLOSION_STRENGTH, VELOCITY, PROJECTILE_COUNT, FOLLOWS_TARGET, FOLLOW_RANGE.conditionally(FOLLOWS_TARGET::get)); - private final EntityReference target = new EntityReference<>(); + private final EntityReference target = dataTracker.startTracking(new EntityReference<>()); protected FireBoltSpell(CustomisedSpellType type) { super(type); diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java index 2c14e4f8..d1bf985f 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/LightSpell.java @@ -38,13 +38,12 @@ public class LightSpell extends AbstractSpell implements TimedSpell, ProjectileD static final TooltipFactory TOOLTIP = TooltipFactory.of(TIME, ORB_COUNT); - private final Timer timer; + private final Timer timer = new Timer(TIME.get(getTraits())); private final List> lights = new ArrayList<>(); protected LightSpell(CustomisedSpellType type) { super(type); - timer = new Timer(TIME.get(getTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java index 57b984c1..1108bd43 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/MimicSpell.java @@ -11,11 +11,10 @@ public class MimicSpell extends AbstractDisguiseSpell implements HomingSpell, Ti static final TooltipFactory TOOLTIP = TimedSpell.TIME; - private final Timer timer; + private final Timer timer = new Timer(TIME.get(getTraits())); protected MimicSpell(CustomisedSpellType type) { super(type); - timer = new Timer(TIME.get(getTraits())); } @Override diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java index 4277ff0c..bb007fe5 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/PortalSpell.java @@ -46,7 +46,7 @@ public class PortalSpell extends AbstractSpell implements PlacementControlSpell. private final DataTracker.Entry targetPortalId = dataTracker.startTracking(TrackableDataType.UUID, Util.NIL_UUID); private final DataTracker.Entry targetPortalPitch = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); private final DataTracker.Entry targetPortalYaw = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); - private final EntityReference teleportationTarget = new EntityReference<>(); + private final EntityReference teleportationTarget = dataTracker.startTracking(new EntityReference<>()); private final DataTracker.Entry pitch = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); private final DataTracker.Entry yaw = dataTracker.startTracking(TrackableDataType.FLOAT, 0F); diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java b/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java index 8b759a18..0e1dcd76 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/EntityReplacementManager.java @@ -67,10 +67,6 @@ class EntityReplacementManager implements Disguise { return disguise; } - @Override - public void setDirty() { - } - @Override public boolean isDead() { return false; diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java index b34606f7..9604dfc1 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/Disguise.java @@ -24,8 +24,6 @@ public interface Disguise extends FlightType.Provider, PlayerDimensions.Provider EntityAppearance getDisguise(); - void setDirty(); - boolean isDead(); default Optional getAppearance() { @@ -57,7 +55,6 @@ public interface Disguise extends FlightType.Provider, PlayerDimensions.Provider } getDisguise().setAppearance(entity); - setDirty(); return this; } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityAppearance.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityAppearance.java index acba1d32..f2c0c56f 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityAppearance.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/EntityAppearance.java @@ -21,6 +21,7 @@ import com.minelittlepony.unicopia.entity.mob.SombraEntity; import com.minelittlepony.unicopia.entity.mob.UEntityAttributes; import com.minelittlepony.unicopia.entity.player.PlayerDimensions; import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.network.track.TrackableObject; import com.minelittlepony.unicopia.projectile.ProjectileUtil; import com.minelittlepony.unicopia.util.NbtSerialisable; import com.mojang.authlib.GameProfile; @@ -51,7 +52,7 @@ import net.minecraft.nbt.NbtElement; import net.minecraft.util.math.Vec3d; import net.minecraft.util.shape.VoxelShape; -public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provider, FlightType.Provider, EntityCollisions.ComplexCollidable { +public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provider, FlightType.Provider, EntityCollisions.ComplexCollidable, TrackableObject { private static final Optional BLOCK_HEIGHT = Optional.of(0.5F); @NotNull @@ -77,6 +78,8 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi @Nullable private NbtCompound entityNbt; + private boolean dirty; + @Nullable public Entity getAppearance() { return entity; @@ -109,6 +112,7 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi entityNbt = entity == null ? null : encodeEntityToNBT(entity); entityId = entityNbt == null ? "" : entityNbt.getString("id"); + markDirty(); } public boolean isPresent() { @@ -393,4 +397,44 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi getAttachments().forEach(e -> EntityCollisions.getCollissionShapes(e.entity(), context, output)); } + public void markDirty() { + dirty = true; + } + + @Override + public Status getStatus() { + if (dirty) { + dirty = false; + return Status.UPDATED; + } + return Status.DEFAULT; + } + + @Override + public void readTrackedNbt(NbtCompound nbt) { + fromNBT(nbt); + } + + @Override + public NbtCompound writeTrackedNbt() { + return toNBT(); + } + + @Override + public void discard(boolean immediate) { + setAppearance(null); + dirty = false; + } + + @Override + public void copyTo(EntityAppearance destination) { + destination.entityId = entityId; + destination.entity = entity; + destination.blockEntity = blockEntity; + destination.attachments.addAll(attachments); + destination.dimensions = dimensions; + destination.tag = tag == null ? null : tag.copy(); + destination.entityNbt = entityNbt == null ? null : entityNbt.copy(); + } + } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java index c4074e27..1a7ac949 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/behaviour/SheepBehaviour.java @@ -65,7 +65,7 @@ public class SheepBehaviour extends EntityBehaviour { } } while (dropAmount-- > 0); } - spell.setDirty(); + spell.getAppearance().ifPresent(EntityAppearance::markDirty); } } } diff --git a/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java b/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java index 9c5c6b74..e918e3e7 100644 --- a/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java +++ b/src/main/java/com/minelittlepony/unicopia/network/track/TrackableDataType.java @@ -11,8 +11,10 @@ import it.unimi.dsi.fastutil.ints.Int2ObjectMap; import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.nbt.NbtCompound; import net.minecraft.network.PacketByteBuf; +import net.minecraft.registry.RegistryKey; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; public record TrackableDataType(int id, PacketCodec codec) { private static final Int2ObjectMap> REGISTRY = new Int2ObjectOpenHashMap<>(); @@ -26,8 +28,16 @@ public record TrackableDataType(int id, PacketCodec codec) { public static final TrackableDataType> RAW_BYTES = of(new Identifier("raw_bytes"), PacketCodec.RAW_BYTES.asOptional()); public static final TrackableDataType> OPTIONAL_POS = of(new Identifier("optional_pos"), PacketCodec.OPTIONAL_POS); + public static final TrackableDataType> OPTIONAL_VECTOR = of(new Identifier("optional_vector"), PacketCodec.OPTIONAL_VECTOR); + private static final TrackableDataType>> OPTIONAL_REGISTRY_KEY = of(new Identifier("optional_registry_key"), PacketCodec.OPTIONAL_REGISTRY_KEY); + public static final TrackableDataType RACE = TrackableDataType.of(Unicopia.id("race"), PacketCodec.ofRegistry(Race.REGISTRY)); + @SuppressWarnings({ "rawtypes", "unchecked" }) + public static TrackableDataType>> ofRegistryKey() { + return (TrackableDataType)OPTIONAL_REGISTRY_KEY; + } + @SuppressWarnings("unchecked") public static TrackableDataType of(PacketByteBuf buffer) { int id = buffer.readInt(); diff --git a/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodec.java b/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodec.java index 03336ec2..cd964b76 100644 --- a/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodec.java +++ b/src/main/java/com/minelittlepony/unicopia/util/serialization/PacketCodec.java @@ -16,9 +16,11 @@ import net.minecraft.nbt.NbtCompound; import net.minecraft.nbt.NbtIo; import net.minecraft.network.PacketByteBuf; import net.minecraft.registry.Registry; +import net.minecraft.registry.RegistryKey; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; public record PacketCodec(PacketByteBuf.PacketReader reader, PacketByteBuf.PacketWriter writer) { public static final PacketCodec BOOLEAN = new PacketCodec<>(PacketByteBuf::readBoolean, PacketByteBuf::writeBoolean); @@ -30,7 +32,7 @@ public record PacketCodec(PacketByteBuf.PacketReader reader, PacketByteBuf public static final PacketCodec UUID = new PacketCodec<>(PacketByteBuf::readUuid, PacketByteBuf::writeUuid); public static final PacketCodec> OPTIONAL_UUID = UUID.asOptional(); - public static final PacketCodec IDENTIFIER = STRING.xMap(Identifier::new, Identifier::toString); + public static final PacketCodec IDENTIFIER = new PacketCodec<>(PacketByteBuf::readIdentifier, PacketByteBuf::writeIdentifier); public static final PacketCodec NBT = new PacketCodec<>(PacketByteBuf::readNbt, PacketByteBuf::writeNbt); @@ -58,6 +60,19 @@ public record PacketCodec(PacketByteBuf.PacketReader reader, PacketByteBuf public static final PacketCodec POS = new PacketCodec<>(PacketByteBuf::readBlockPos, PacketByteBuf::writeBlockPos); public static final PacketCodec> OPTIONAL_POS = POS.asOptional(); + public static final PacketCodec VECTOR = new PacketCodec<>(buffer -> new Vec3d(buffer.readDouble(), buffer.readDouble(), buffer.readDouble()), (buffer, vector) -> { + buffer.writeDouble(vector.x); + buffer.writeDouble(vector.y); + buffer.writeDouble(vector.z); + }); + public static final PacketCodec> OPTIONAL_VECTOR = VECTOR.asOptional(); + public static final PacketCodec> REGISTRY_KEY = new PacketCodec<>(buffer -> { + return RegistryKey.of(RegistryKey.ofRegistry(IDENTIFIER.read(buffer)), IDENTIFIER.read(buffer)); + }, (buffer, key) -> { + IDENTIFIER.write(buffer, key.getRegistry()); + IDENTIFIER.write(buffer, key.getValue()); + }); + public static final PacketCodec>> OPTIONAL_REGISTRY_KEY = REGISTRY_KEY.asOptional(); public static final PacketCodec ofRegistry(Registry registry) { return INT.xMap(registry::get, registry::getRawId); From e8649aca7de8c19e07766a51bbb8d6be3aec0129 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 21 Sep 2024 21:40:40 +0100 Subject: [PATCH 034/110] Remove redundant effect nbt field --- .../java/com/minelittlepony/unicopia/entity/Creature.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Creature.java b/src/main/java/com/minelittlepony/unicopia/entity/Creature.java index c319f104..4be62edd 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Creature.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Creature.java @@ -11,7 +11,6 @@ import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.Race; import com.minelittlepony.unicopia.WeaklyOwned; import com.minelittlepony.unicopia.ability.magic.*; -import com.minelittlepony.unicopia.ability.magic.spell.Spell; import com.minelittlepony.unicopia.ability.magic.spell.effect.TargetSelecter; import com.minelittlepony.unicopia.entity.ai.BreakHeartGoal; import com.minelittlepony.unicopia.entity.ai.DynamicTargetGoal; @@ -302,9 +301,6 @@ public class Creature extends Living implements WeaklyOwned.Mutabl @Override public void toNBT(NbtCompound compound) { super.toNBT(compound); - getSpellSlot().get().ifPresent(effect -> { - compound.put("effect", Spell.writeNbt(effect)); - }); compound.put("master", getMasterReference().toNBT()); physics.toNBT(compound); compound.putBoolean("discorded", isDiscorded()); @@ -313,9 +309,6 @@ public class Creature extends Living implements WeaklyOwned.Mutabl @Override public void fromNBT(NbtCompound compound) { super.fromNBT(compound); - if (compound.contains("effect")) { - getSpellSlot().put(Spell.readNbt(compound.getCompound("effect"))); - } if (compound.contains("master", NbtElement.COMPOUND_TYPE)) { owner.fromNBT(compound.getCompound("master")); if (owner.isSet()) { From 89124eb146dbe0d702ddc78adecd3757b90c74c9 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 21 Sep 2024 21:41:04 +0100 Subject: [PATCH 035/110] Fixed disguises applied via commands not remaining when applied to a non-changeling entity --- .../ability/magic/spell/DispersableDisguiseSpell.java | 11 ++++++++++- .../unicopia/command/DisguiseCommand.java | 10 +++++++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DispersableDisguiseSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DispersableDisguiseSpell.java index 7f614bc6..2b7f7cb8 100644 --- a/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DispersableDisguiseSpell.java +++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/DispersableDisguiseSpell.java @@ -26,11 +26,18 @@ public class DispersableDisguiseSpell extends AbstractDisguiseSpell implements I private final DataTracker.Entry suppressed = dataTracker.startTracking(TrackableDataType.BOOLEAN, false); private int suppressionCounter; + private boolean forced; + public DispersableDisguiseSpell(CustomisedSpellType type) { super(type); setHidden(true); } + public void setForced() { + forced = true; + setHidden(false); + } + @Override public boolean isVulnerable(Caster otherSource, Spell other) { return suppressionCounter <= otherSource.getLevel().get(); @@ -59,7 +66,7 @@ public class DispersableDisguiseSpell extends AbstractDisguiseSpell implements I } } - if (!source.canUse(Abilities.DISGUISE)) { + if (!forced && !source.canUse(Abilities.DISGUISE)) { setDead(); } @@ -91,12 +98,14 @@ public class DispersableDisguiseSpell extends AbstractDisguiseSpell implements I public void toNBT(NbtCompound compound) { super.toNBT(compound); compound.putInt("suppressionCounter", suppressionCounter); + compound.putBoolean("forced", forced); } @Override public void fromNBT(NbtCompound compound) { super.fromNBT(compound); suppressionCounter = compound.getInt("suppressionCounter"); + forced = compound.getBoolean("forced"); if (suppressionCounter > 0) { suppressed.set(true); } diff --git a/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java b/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java index d735c89a..5dba2c32 100644 --- a/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java +++ b/src/main/java/com/minelittlepony/unicopia/command/DisguiseCommand.java @@ -4,8 +4,10 @@ import java.util.function.Function; import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.InteractionManager; +import com.minelittlepony.unicopia.ability.Abilities; import com.minelittlepony.unicopia.ability.magic.SpellPredicate; import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod; +import com.minelittlepony.unicopia.ability.magic.spell.DispersableDisguiseSpell; import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType; import com.minelittlepony.unicopia.entity.player.Pony; import com.mojang.authlib.GameProfile; @@ -81,7 +83,13 @@ public class DisguiseCommand { Pony iplayer = Pony.of(player); iplayer.getSpellSlot().get(SpellType.CHANGELING_DISGUISE) - .orElseGet(() -> SpellType.CHANGELING_DISGUISE.withTraits().apply(iplayer, CastingMethod.INNATE)) + .orElseGet(() -> { + DispersableDisguiseSpell spell = SpellType.CHANGELING_DISGUISE.withTraits().apply(iplayer, CastingMethod.INNATE); + if (!iplayer.canUse(Abilities.DISGUISE)) { + spell.setForced(); + } + return spell; + }) .setDisguise(entity); if (source.getEntity() == player) { From c75b4b36b8a278a11f482d3f37d4c133427455a4 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 21 Sep 2024 21:41:21 +0100 Subject: [PATCH 036/110] Update iris dependency --- build.gradle | 7 ++++++- gradle.properties | 1 + .../unicopia/client/gui/DismissSpellScreen.java | 5 ----- 3 files changed, 7 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index de730eec..4682312e 100644 --- a/build.gradle +++ b/build.gradle @@ -102,7 +102,12 @@ dependencies { if (project.use_sodium == '1') { modCompileOnly "maven.modrinth:indium:${project.indium_version}", { exclude group: "net.fabricmc.fabric-api" } modCompileOnly "maven.modrinth:sodium:${project.sodium_version}", { exclude group: "net.fabricmc.fabric-api" } - // modCompileOnly "maven.modrinth:iris:${project.iris_version}", { exclude group: "net.fabricmc.fabric-api" } + if (project.use_iris == '1') { + modCompileOnly "maven.modrinth:iris:${project.iris_version}", { exclude group: "net.fabricmc.fabric-api" } + modImplementation "org.anarres:jcpp:1.4.14" + modImplementation "org.antlr:antlr4-runtime:4.13.1" + modImplementation "io.github.douira:glsl-transformer:2.0.1" + } } if (project.tmi_type == 'emi') { diff --git a/gradle.properties b/gradle.properties index 25ccc1c3..a11af593 100644 --- a/gradle.properties +++ b/gradle.properties @@ -33,6 +33,7 @@ org.gradle.daemon=false use_trinkets=1 use_pehkui=0 use_sodium=1 + use_iris=1 farmers_delight_version=1.20.1-2.0.9 pehkui_version=3.7.8+1.14.4-1.20.1 diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java index 23b90dc6..cddf13b9 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java @@ -101,11 +101,6 @@ public class DismissSpellScreen extends GameGui { matrices.pop(); } - @Override - public void renderInGameBackground(DrawContext context) { - - } - @Override public boolean shouldPause() { return false; From 5b443f118d72fa8453d20b572af30b76013a6e48 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 21 Sep 2024 22:46:18 +0100 Subject: [PATCH 037/110] Adjust changeling hive size --- .../worldgen/structure/abandoned_changeling_hive.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json b/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json index 70b16c5a..452e16aa 100644 --- a/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json +++ b/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json @@ -3,7 +3,7 @@ "biomes": "#minecraft:is_forest", "max_distance_from_center": 112, "project_start_to_heightmap": "WORLD_SURFACE_WG", - "size": 7, + "size": 20, "spawn_overrides": { "monster": { "bounding_box": "piece", @@ -21,7 +21,7 @@ "absolute": -7 }, "start_pool": "unicopia:changeling_hive/start", - "step": "underground_decoration", + "step": "underground_structures", "terrain_adaptation": "none", "use_expansion_hack": false } \ No newline at end of file From f8018cb6fc54e25f566d0e76c3a842da7374f5f5 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 14:48:34 +0100 Subject: [PATCH 038/110] Improve changeling hive generation. Fixes #398 --- .../unicopia/server/world/UWorldGen.java | 6 ++ .../gen/CaveCarvingStructureProcessor.java | 36 ++++++++++ .../gen/SurfaceGrowthStructureProcessor.java | 67 ++++++++++++++++++ .../changeling_hive/entrance_large_lower.nbt | Bin 0 -> 4916 bytes .../changeling_hive/entrance_large_upper.nbt | Bin 0 -> 4511 bytes .../floor_decoration/empty.nbt | Bin 0 -> 282 bytes .../floor_decoration/slime_1.nbt | Bin 0 -> 327 bytes .../floor_decoration/slime_2.nbt | Bin 0 -> 329 bytes .../floor_decoration/slime_3.nbt | Bin 0 -> 327 bytes .../floor_decoration/spikes.nbt | Bin 0 -> 313 bytes .../changeling_hive/roof_decoration/empty.nbt | Bin 0 -> 271 bytes .../changeling_hive/roof_decoration/slime.nbt | Bin 0 -> 327 bytes .../roof_decoration/spikes.nbt | Bin 0 -> 303 bytes .../processor_list/changeling_hive_decay.json | 17 ++++- .../changeling_hive_entrance_decay.json | 32 +++++++++ .../changeling_hive_surfacing.json | 13 ++++ .../structure/abandoned_changeling_hive.json | 2 +- .../changeling_hive/chamber_decors.json | 16 ++--- .../changeling_hive/floor_additions.json | 50 +++++++++++++ .../floor_additions_termination.json | 14 ++++ .../changeling_hive/main_entrance_shafts.json | 14 ++++ .../changeling_hive/pit_decors.json | 20 ++---- .../changeling_hive/roof_additions.json | 32 +++++++++ .../roof_additions_termination.json | 14 ++++ .../template_pool/changeling_hive/start.json | 22 +----- 25 files changed, 305 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/gen/CaveCarvingStructureProcessor.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/gen/SurfaceGrowthStructureProcessor.java create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_lower.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_upper.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/empty.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_1.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_2.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_3.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/spikes.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/empty.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/slime.nbt create mode 100644 src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/spikes.nbt create mode 100644 src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_entrance_decay.json create mode 100644 src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_surfacing.json create mode 100644 src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/floor_additions.json create mode 100644 src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/floor_additions_termination.json create mode 100644 src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/main_entrance_shafts.json create mode 100644 src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/roof_additions.json create mode 100644 src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/roof_additions_termination.json diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java index c7c781a6..5100d075 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java @@ -6,7 +6,9 @@ import java.util.function.Consumer; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.block.ShellsBlock; import com.minelittlepony.unicopia.block.UBlocks; +import com.minelittlepony.unicopia.server.world.gen.CaveCarvingStructureProcessor; import com.minelittlepony.unicopia.server.world.gen.OverworldBiomeSelectionCallback; +import com.minelittlepony.unicopia.server.world.gen.SurfaceGrowthStructureProcessor; import com.minelittlepony.unicopia.util.registry.DynamicRegistry; import net.fabricmc.fabric.api.biome.v1.BiomeModifications; @@ -23,6 +25,7 @@ import net.minecraft.registry.RegistryKeys; import net.minecraft.registry.tag.BiomeTags; import net.minecraft.sound.BiomeMoodSound; import net.minecraft.sound.SoundEvents; +import net.minecraft.structure.processor.StructureProcessorType; import net.minecraft.util.collection.DataPool; import net.minecraft.util.math.Direction; import net.minecraft.util.math.Vec3i; @@ -120,6 +123,9 @@ public interface UWorldGen { .build(); }); + StructureProcessorType SURFACE_GROWTH_STRUCTURE_PROCESSOR = Registry.register(Registries.STRUCTURE_PROCESSOR, Unicopia.id("surface_growth"), () -> SurfaceGrowthStructureProcessor.CODEC); + StructureProcessorType CAVE_CARVING_STRUCTURE_PROCESSOR = Registry.register(Registries.STRUCTURE_PROCESSOR, Unicopia.id("cave_carving"), () -> CaveCarvingStructureProcessor.CODEC); + @SafeVarargs static T applyAll(T t, Consumer ...consumers) { for (Consumer consumer : consumers) { diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CaveCarvingStructureProcessor.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CaveCarvingStructureProcessor.java new file mode 100644 index 00000000..cfb2db26 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CaveCarvingStructureProcessor.java @@ -0,0 +1,36 @@ +package com.minelittlepony.unicopia.server.world.gen; + +import org.jetbrains.annotations.Nullable; + +import com.minelittlepony.unicopia.server.world.UWorldGen; +import com.mojang.serialization.Codec; +import net.minecraft.structure.StructurePlacementData; +import net.minecraft.structure.StructureTemplate; +import net.minecraft.structure.processor.StructureProcessor; +import net.minecraft.structure.processor.StructureProcessorType; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.Heightmap; +import net.minecraft.world.WorldView; + +public class CaveCarvingStructureProcessor extends StructureProcessor { + public static final Codec CODEC = Codec.unit(new CaveCarvingStructureProcessor()); + + @Override + protected StructureProcessorType getType() { + return UWorldGen.SURFACE_GROWTH_STRUCTURE_PROCESSOR; + } + + @Nullable + @Override + public StructureTemplate.StructureBlockInfo process( + WorldView world, + BlockPos pos, + BlockPos pivot, + StructureTemplate.StructureBlockInfo originalBlockInfo, + StructureTemplate.StructureBlockInfo currentBlockInfo, + StructurePlacementData data + ) { + int topY = world.getTopY(Heightmap.Type.WORLD_SURFACE_WG, currentBlockInfo.pos().getX(), currentBlockInfo.pos().getZ()); + return currentBlockInfo.pos().getY() > topY && world.isAir(currentBlockInfo.pos()) ? null : currentBlockInfo; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/SurfaceGrowthStructureProcessor.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/SurfaceGrowthStructureProcessor.java new file mode 100644 index 00000000..33ef60c7 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/SurfaceGrowthStructureProcessor.java @@ -0,0 +1,67 @@ +package com.minelittlepony.unicopia.server.world.gen; + +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +import com.minelittlepony.unicopia.server.world.UWorldGen; +import com.mojang.serialization.Codec; +import com.mojang.serialization.codecs.RecordCodecBuilder; + +import net.minecraft.block.BlockState; +import net.minecraft.structure.StructurePlacementData; +import net.minecraft.structure.StructureTemplate; +import net.minecraft.structure.processor.StructureProcessor; +import net.minecraft.structure.processor.StructureProcessorType; +import net.minecraft.structure.rule.RuleTest; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.ServerWorldAccess; + +public class SurfaceGrowthStructureProcessor extends StructureProcessor { + public static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( + RuleTest.TYPE_CODEC.fieldOf("input_predicate").forGetter(rule -> rule.inputPredicate), + BlockState.CODEC.fieldOf("output_state").forGetter(rule -> rule.outputState) + ).apply(instance, SurfaceGrowthStructureProcessor::new)); + + private final RuleTest inputPredicate; + private final BlockState outputState; + + public SurfaceGrowthStructureProcessor(RuleTest inputPredicate, BlockState outputState) { + this.inputPredicate = inputPredicate; + this.outputState = outputState; + } + + @Override + protected StructureProcessorType getType() { + return UWorldGen.SURFACE_GROWTH_STRUCTURE_PROCESSOR; + } + + @SuppressWarnings("deprecation") + @Override + public List reprocess( + ServerWorldAccess world, + BlockPos pos, + BlockPos pivot, + List originalBlockInfos, + List currentBlockInfos, + StructurePlacementData data + ) { + Map positionalInfos = currentBlockInfos.stream().collect(Collectors.toMap( + StructureTemplate.StructureBlockInfo::pos, + Function.identity() + )); + + return currentBlockInfos.stream().map(currentBlockInfo -> { + StructureTemplate.StructureBlockInfo aboveBlockInfo = positionalInfos.get(currentBlockInfo.pos().up()); + BlockState currentState = aboveBlockInfo == null ? world.getBlockState(currentBlockInfo.pos().up()) : aboveBlockInfo.state(); + if ((currentState.isAir() || currentState.isReplaceable()) + && inputPredicate.test(currentBlockInfo.state(), Random.create(MathHelper.hashCode(currentBlockInfo.pos())))) { + return new StructureTemplate.StructureBlockInfo(currentBlockInfo.pos(), outputState, currentBlockInfo.nbt()); + } + return currentBlockInfo; + }).collect(Collectors.toList()); + } +} diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_lower.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_lower.nbt new file mode 100644 index 0000000000000000000000000000000000000000..2a6cd5e5994ef45fe5dd4ab84793728f0e7166c4 GIT binary patch literal 4916 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 literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_1.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_1.nbt new file mode 100644 index 0000000000000000000000000000000000000000..86e553a77752d5174b62baff89541c6e09856ef5 GIT binary patch literal 327 zcmV-N0l5AjiwFP!00000|BX;hPs1<__11N?odjqXega3tb!X0q6W7X1-7F(bqQqqy zzaD3UO>7q;S&hFLOSQ~*G(iPSXTHB{u-u%QI`)G%LLuRcq%~Zw6O)ny9@TYz=h_`5KJB?O ZEm{{Z$oNh%WenUhd;>5yS9Uf6008VtkM{ro literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_2.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_2.nbt new file mode 100644 index 0000000000000000000000000000000000000000..185d053bcaa849240b629405dc0ef9cc9b260772 GIT binary patch literal 329 zcmV-P0k-}hiwFP!00000|BX;hPs1<__10~)odjqXega1%jyrQkoVZqA>ZTcK93?5! z`1Lp&Y+}0*$%>r#`F+#?70jafq5=SNO{AvzuAn5BOfnQ9p9&Tm%jzT6d7^^CbNmIt z4^WzUOql5KQbXZ3sf78KjZ07lwiY**N|-qu2p&gg6nlef)uYp7jnhqUKIy5m%%Q=y z6?%3u@0l&!4aSiQ*rhcMKJ80bcE+J?j+76lb#V+GDr!_Ocvry6TWJTe)A(RGn6y8N zT}85_GRL2f5~ikw`!n6v=!m-#772r<^l#;G9TQx{G?AGbkCsxRL$Wp0Z-G69oV-}v z$y~6kHMKDB&_>B`u6UG0C(j~v_L{Rin;-U30EWldkk)XyPE1M;cu-fjymL+DG4-cK bSFT0u@&yyVQ-~P^w+X%hp_V2{Hv#|v<29Gh literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_3.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_3.nbt new file mode 100644 index 0000000000000000000000000000000000000000..53574e14b0c8f8321f46475426f3f1fea79b46e1 GIT binary patch literal 327 zcmV-N0l5AjiwFP!00000|BX;RPs1<}y*5orQVCEOegY!{TW4m(#2Q_li|gXpmVKcr zzn*got!Ni4ovgF(-TP<&YM3SSMFjxlnn+FaT|-5V4I4_3PYv_6_39%vd7_3Q`1A{c zAD}d4Vq`kJG*GxTS5R)faST=T*5cYy1v7^O!Q<$R^1@{b3Hb3l>0E{0~OIpL_Ix#6Z;89)Ycdp%0;?tfh Z)1r0pf{gDJQ^vq8!#Av(Q=>Kl007qdn^^z= literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/spikes.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/spikes.nbt new file mode 100644 index 0000000000000000000000000000000000000000..c3932214c36bf1478af26bef2737f593157af818 GIT binary patch literal 313 zcmV-90ml9xiwFP!00000|BX>iPXaLz9azBKB~imce}YHvoIM*)UYlWeb{XilO*=^N z*E+1tmFQVM>r!1+$g)%{JA!qkQiHVY>0`1j^{G#g(NJCJqOJhn?fb2gYTyM%R;N*PAuJ(PL-5j|SUT z>Alnb;Jt;LfgLpwJ6X~Yf{Ik>wY^x2_Ffw%fi7tpyHQqOo&()ztKdrER1^T(j-nm?i7E5(#Ca4qlw L4FAa=A_4#aTq%?h literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/empty.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/empty.nbt new file mode 100644 index 0000000000000000000000000000000000000000..bd44b266639761e1f44abb40d6834671cbebd6c2 GIT binary patch literal 271 zcmV+q0r37GiwFP!00000|BaB#P6IIvMK4Sr=~SYqAHkM=*Q^mMwj|_OF4#t*mkX{moALL`Q>(QtVm( z3!F7n!KbUOuc|P16fw(PgnIz^nqh>nJ>#wnVZgW(?e*EoU%cTo{P9Yh&g)x VL`tt5Q`x|s;sYzGLBF>F002Eig!cdd literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/slime.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/slime.nbt new file mode 100644 index 0000000000000000000000000000000000000000..521802b8222631121cec0b2a68a8e0dd04e2905d GIT binary patch literal 327 zcmV-N0l5AjiwFP!00000|CNzJQ^GJ1g%?U8Ei>Y9@F#fn&e^l$$!lk6w`DO+GRam3 zf4vC^Dtf@oWOCTIZ{L0?0ScG|ey0oo(jA@N0u&ixVG58=0n@d%^=l}TqJYfVaB4cA z4Dui-^x1K#8C_^bP(o(bq9ET|HUi39t#PeM!Ng!sa6cHXtz%r(8#EnhHeI#hH+t~a zwiPx_OlVD%J8Ly8dNx#hY-L5glf8m@%La9IoVfVr7W+&FOQ*4>K5kk$&(^c-j~SPN zG}X!bM?t}u8@T-%v*j+}PQg^rcO=&a{sYeV0?s&UW)3xp(1Cdg<+HbreEJg=Yj#JT z8pvDJAri~O1|22eCgz+xC4P73I6-qyl^cQ#n&4Wm8r^@r<`GupiH9|3gR2OGoK1eA Zi!09`QSgO)NF8t^@BxT&kzkhs0045jlU4u# literal 0 HcmV?d00001 diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/spikes.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/spikes.nbt new file mode 100644 index 0000000000000000000000000000000000000000..7a388fabc20f4bec549d75eba9bcd8dab663ccbc GIT binary patch literal 303 zcmV+~0nq**iwFP!00000|BX@2Zo)7OHnc!mq%m>e5q903^Ul*wyH+N3iy=*-#0;^g zUjiE2;4({A6vh7jQUg>_M*gG%0CJB~kMmi9A}cIR5pq>9-596$vCb0}6yC+}rE3*1 ziGo7sOAUqHh=R$^u@z9k8G{=`3QCIu!PCLAcAjyqw`hAZZ2M-*AM_lY>l$p^#O`bw z_s$tu3~WgU>|{-Ymy?2d#}-XEa39X-CY({4nRzrMLgzedsNaI~6ms5)u|u7}p={mJCSm1k z4s3N}v5B7d>3eRL=gCnrjb|;hgKv%$ Date: Tue, 24 Sep 2024 15:00:42 +0100 Subject: [PATCH 039/110] Fixed non-pegasi not able to jump out of cloud blocks --- .../com/minelittlepony/unicopia/block/cloud/CloudBlock.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java index fd526300..05953dc8 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -105,10 +105,9 @@ public class CloudBlock extends Block implements CloudLike { entity.addVelocity(0, 0.07, 0); entity.setOnGround(true); } - entity.setVelocity(entity.getVelocity().multiply(0.9F, 1, 0.9F)); - } else { - entity.setVelocity(entity.getVelocity().multiply(0.9F)); } + + entity.setVelocity(entity.getVelocity().multiply(0.9F, 1, 0.9F)); } @Override From 1ff0e89724212f06229a387f3ba9f4353c72e9c9 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:01:13 +0100 Subject: [PATCH 040/110] Creative players can now interact with cloud blocks regardless of tribe. Closes #461 --- .../java/com/minelittlepony/unicopia/entity/player/Pony.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java index cba9e735..ca4aa870 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Pony.java @@ -224,6 +224,11 @@ public class Pony extends Living implements Copyable, Update return compositeRace; } + @Override + public boolean collidesWithClouds() { + return getCompositeRace().canInteractWithClouds() || entity.isCreative(); + } + @Override public void setSpecies(Race race) { race = race.validate(entity); From 797e2101b529a5861e3494190888c815f176937c Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:16:18 +0100 Subject: [PATCH 041/110] Fix layering on the tribe confirmation screen --- .../client/gui/TribeConfirmationScreen.java | 18 +++++------------- .../structure/abandoned_changeling_hive.json | 2 +- 2 files changed, 6 insertions(+), 14 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java index a4a82e64..27fe88d7 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java @@ -104,10 +104,12 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud { @Override public void render(DrawContext context, int mouseX, int mouseY, float delta) { + context.getMatrices().push(); + context.getMatrices().translate(0, 0, -2); if (parent != null) { context.getMatrices().push(); context.getMatrices().translate(0, 0, -100); - parent.render(context, 0, 0, delta); + parent.render(context, -1, -1, delta); context.getMatrices().pop(); } renderBackground(context); @@ -120,30 +122,20 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud { int left = (width - columnWidth) / 2; top += 40; - final int zOffset = 0; context.drawTexture(TribeSelectionScreen.TEXTURE, left + zOffset, top, 0, 70, 123, columnHeight); - context.drawTexture(TribeSelectionScreen.TEXTURE, left + segmentWidth + zOffset, top, 20, 70, 123, columnHeight); - - context.drawTexture(TribeSelectionScreen.TEXTURE, width - left - segmentWidth + zOffset, top, 10, 70, 123, columnHeight); - + context.drawTexture(TribeSelectionScreen.TEXTURE, width - left - segmentWidth + zOffset + 1, top, 10, 70, 123, columnHeight); top -= 31; - left = width / 2; - context.drawTexture(TribeSelectionScreen.TEXTURE, left - 55, top, 140, 70, 21, 50); context.drawTexture(TribeSelectionScreen.TEXTURE, left + 35, top, 148, 70, 21, 50); - textBody.render(context, mouseX, mouseY, delta); - - context.getMatrices().push(); - context.getMatrices().translate(0, 0, 2); + context.getMatrices().pop(); context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 5, 10, 70, 69, 50); context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 15, 10, 70, 69, 50); super.render(context, mouseX, mouseY, delta); - context.getMatrices().pop(); } @Override diff --git a/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json b/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json index 978a4940..d88b505b 100644 --- a/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json +++ b/src/main/resources/data/unicopia/worldgen/structure/abandoned_changeling_hive.json @@ -3,7 +3,7 @@ "biomes": "#minecraft:is_forest", "max_distance_from_center": 112, "project_start_to_heightmap": "WORLD_SURFACE_WG", - "size": 20, + "size": 7, "spawn_overrides": { "monster": { "bounding_box": "piece", From 95da98b8c3024db49fae2d19604d006250441bcf Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:16:49 +0100 Subject: [PATCH 042/110] Fix #466 --- src/main/java/com/minelittlepony/unicopia/Race.java | 2 +- src/main/resources/assets/unicopia/lang/en_us.json | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/Race.java b/src/main/java/com/minelittlepony/unicopia/Race.java index 84994481..8607c091 100644 --- a/src/main/java/com/minelittlepony/unicopia/Race.java +++ b/src/main/java/com/minelittlepony/unicopia/Race.java @@ -70,7 +70,7 @@ public record Race ( * This is used if there are no other races. */ public static final Race UNSET = register("unset", new Builder().availability(Availability.COMMANDS)); - public static final Race HUMAN = register("human", new Builder().availability(Availability.COMMANDS)); + public static final Race HUMAN = register("human", new Builder()); public static final Race EARTH = register("earth", new Builder().foraging().earth() .abilities(Abilities.HUG, Abilities.STOMP, Abilities.KICK, Abilities.GROW) ); diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index 3d8903f2..6005597f 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -799,6 +799,7 @@ "gui.unicopia.tribe_selection.options": "Available Tribes:", "gui.unicopia.tribe_selection.options.disabled": "Option Unavailable", + "gui.unicopia.tribe_selection.describe.unicopia.human": "Got it alone", "gui.unicopia.tribe_selection.describe.unicopia.earth": "Join the Earth Tribe", "gui.unicopia.tribe_selection.describe.unicopia.unicorn": "Join the Unicorn Tribe, master the arcane arts", "gui.unicopia.tribe_selection.describe.unicopia.pegasus": "Join the Pegasus Tribe, soar with the Wonderbolts", From bee81cae748eefde33eecc1af4dfb1dad25aeacb Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:45:26 +0100 Subject: [PATCH 043/110] Make gemstones edible for earth ponies. Fixes #460 --- .../java/com/minelittlepony/unicopia/UConventionalTags.java | 1 + .../unicopia/datagen/providers/DietProfileGenerator.java | 2 ++ .../unicopia/datagen/providers/FoodGroupsGenerator.java | 1 + .../unicopia/datagen/providers/tag/UItemTagProvider.java | 1 + 4 files changed, 5 insertions(+) diff --git a/src/main/java/com/minelittlepony/unicopia/UConventionalTags.java b/src/main/java/com/minelittlepony/unicopia/UConventionalTags.java index 6b54e607..31b02f7f 100644 --- a/src/main/java/com/minelittlepony/unicopia/UConventionalTags.java +++ b/src/main/java/com/minelittlepony/unicopia/UConventionalTags.java @@ -46,6 +46,7 @@ public interface UConventionalTags { TagKey FRUITS = item("fruits"); TagKey WORMS = item("worms"); TagKey ROCKS = item("rocks"); + TagKey GEMS = item("gems"); TagKey RAW_INSECT = item("raw_insect"); TagKey COOKED_INSECT = item("cooked_insect"); diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/DietProfileGenerator.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/DietProfileGenerator.java index 4034021f..cfa28601 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/DietProfileGenerator.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/DietProfileGenerator.java @@ -148,12 +148,14 @@ public class DietProfileGenerator { bakedGoodExtremePreference, pineconeMultiplier, properMeatStandards, seaFoodExclusions, // They have a sweet tooth new Multiplier.Builder().tag(Unicopia.id("candy")).tag(Unicopia.id("desserts")).tag(Unicopia.id("rocks")).hunger(2.5F).saturation(1.7F).build(), + new Multiplier.Builder().tag(Unicopia.id("gems")).hunger(0.5F).saturation(0.7F).build(), new Multiplier.Builder().tag(Unicopia.id("fish/cooked")).hunger(0.2F).saturation(0.3F).build(), new Multiplier.Builder().tag(Unicopia.id("insect/cooked")).hunger(0.1F).saturation(0.1F).build(), new Multiplier.Builder().tag(Unicopia.id("meat/cooked")).hunger(0.1F).saturation(0.1F).build() ), List.of( // Candy and rocks gives them a massive saturation boost. Maybe too much? new FoodGroupEffects.Builder().tag(Unicopia.id("candy")).tag(Unicopia.id("rocks")).food(UFoodComponents.builder(5, 12).alwaysEdible()).build(), + new FoodGroupEffects.Builder().tag(Unicopia.id("gems")).food(UFoodComponents.builder(2, 1.5F).snack().alwaysEdible()).build(), new FoodGroupEffects.Builder().tag(Unicopia.id("desserts")).food(UFoodComponents.builder(12, 32).snack().alwaysEdible()).build() ), Optional.empty())); // Pegasi prefer fish over other food sources diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/FoodGroupsGenerator.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/FoodGroupsGenerator.java index a30de498..47864d46 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/FoodGroupsGenerator.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/FoodGroupsGenerator.java @@ -31,6 +31,7 @@ public class FoodGroupsGenerator { exporter.accept(Unicopia.id("desserts"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.DESSERTS).food(FoodComponents.COOKIE)); exporter.accept(Unicopia.id("fruit"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.FRUITS).food(UFoodComponents.BANANA)); exporter.accept(Unicopia.id("rocks"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.ROCKS).tag(UTags.Items.ROCK_STEWS).food(FoodComponents.MUSHROOM_STEW)); + exporter.accept(Unicopia.id("gems"), new FoodGroupEffects.Builder().tag(UConventionalTags.Items.GEMS)); exporter.accept(Unicopia.id("shells"), new FoodGroupEffects.Builder().tag(UTags.Items.SHELLS).food(UFoodComponents.SHELL)); exporter.accept(Unicopia.id("special_shells"), new FoodGroupEffects.Builder().tag(UTags.Items.SPECIAL_SHELLS).food(UFoodComponents.SHELLY)); exporter.accept(Unicopia.id("love"), new FoodGroupEffects.Builder().tag(UTags.Items.CONTAINER_WITH_LOVE).food(UFoodComponents.LOVE_MUG).ailment(new CompoundAffliction(List.of( diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java index 9e579480..ec4dd783 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UItemTagProvider.java @@ -353,6 +353,7 @@ public class UItemTagProvider extends FabricTagProvider.ItemTagProvider { getOrCreateTagBuilder(UConventionalTags.Items.WORMS).add(UItems.WHEAT_WORMS); getOrCreateTagBuilder(UConventionalTags.Items.STICKS).add(Items.STICK); getOrCreateTagBuilder(UConventionalTags.Items.ROCKS).add(UItems.ROCK); + getOrCreateTagBuilder(UConventionalTags.Items.GEMS).add(UItems.GEMSTONE, UItems.BOTCHED_GEM); getOrCreateTagBuilder(UConventionalTags.Items.PINECONES).add(UItems.PINECONE); getOrCreateTagBuilder(UConventionalTags.Items.PINEAPPLES).add(UItems.PINEAPPLE); getOrCreateTagBuilder(UConventionalTags.Items.MANGOES).add(UItems.MANGO); From 36a8a9d018709e4a09fff6b969416cbf3471a2b6 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:45:49 +0100 Subject: [PATCH 044/110] Reduce hunger granted by eating placed hay bales --- .../java/com/minelittlepony/unicopia/block/EdibleBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/EdibleBlock.java b/src/main/java/com/minelittlepony/unicopia/block/EdibleBlock.java index e6bf0482..707853b1 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/EdibleBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/EdibleBlock.java @@ -205,7 +205,7 @@ public class EdibleBlock extends HayBlock { if (world.random.nextInt(10) == 0) { player.playSound(USounds.Vanilla.ENTITY_PLAYER_BURP, 1, player.getSoundPitch()); } - player.getHungerManager().add(4, 2.3F); + player.getHungerManager().add(2, 1.3F); } return ActionResult.SUCCESS; } From c7a0c7b527bb4c860a81af81b577c11689b220b1 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 15:52:19 +0100 Subject: [PATCH 045/110] Reduce chance of mobs reproducing when they have the corrupt influence effect. Fixes #467 --- src/main/java/com/minelittlepony/unicopia/entity/Living.java | 2 +- .../unicopia/entity/effect/CorruptInfluenceStatusEffect.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/Living.java b/src/main/java/com/minelittlepony/unicopia/entity/Living.java index 756a4491..e109876a 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/Living.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/Living.java @@ -381,7 +381,7 @@ public abstract class Living implements Equine, Caste } } - if (entity instanceof HostileEntity mob && mob.hasStatusEffect(UEffects.CORRUPT_INFLUENCE) && mob.getRandom().nextInt(4) == 0) { + if (entity instanceof HostileEntity mob && mob.hasStatusEffect(UEffects.CORRUPT_INFLUENCE) && mob.getRandom().nextInt(4000) == 0) { CorruptInfluenceStatusEffect.reproduce(mob); } diff --git a/src/main/java/com/minelittlepony/unicopia/entity/effect/CorruptInfluenceStatusEffect.java b/src/main/java/com/minelittlepony/unicopia/entity/effect/CorruptInfluenceStatusEffect.java index bf98ef9d..a30d7656 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/effect/CorruptInfluenceStatusEffect.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/CorruptInfluenceStatusEffect.java @@ -89,6 +89,9 @@ public class CorruptInfluenceStatusEffect extends StatusEffect { } } + if (mob.getRandom().nextInt(4) != 0) { + clone.clearStatusEffects(); + } mob.getWorld().spawnEntity(clone); if (!mob.isSilent()) { From c7c8e0971b45bf621cceff1763e76026815b87f3 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 18:34:58 +0100 Subject: [PATCH 046/110] Adjust polearm strengths --- .../com/minelittlepony/unicopia/item/UItems.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/item/UItems.java b/src/main/java/com/minelittlepony/unicopia/item/UItems.java index c1f8081e..083e4ef8 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/UItems.java +++ b/src/main/java/com/minelittlepony/unicopia/item/UItems.java @@ -146,12 +146,12 @@ public interface UItems { Item COPPER_HORSE_SHOE = register("copper_horse_shoe", new HorseShoeItem(new Item.Settings().maxDamage(250), 6, 0.5F, 0.8F), ItemGroups.COMBAT); Item NETHERITE_HORSE_SHOE = register("netherite_horse_shoe", new HorseShoeItem(new Item.Settings().maxDamage(800), 3, 0.7F, 1.2F), ItemGroups.COMBAT); - Item WOODEN_POLEARM = register("wooden_polearm", new PolearmItem(ToolMaterials.WOOD, 2, -3.6F, 2, new Item.Settings()), ItemGroups.COMBAT); - Item STONE_POLEARM = register("stone_polearm", new PolearmItem(ToolMaterials.STONE, 2, -3.6F, 2, new Item.Settings()), ItemGroups.COMBAT); - Item IRON_POLEARM = register("iron_polearm", new PolearmItem(ToolMaterials.IRON, 2, -3.6F, 3, new Item.Settings()), ItemGroups.COMBAT); - Item GOLDEN_POLEARM = register("golden_polearm", new PolearmItem(ToolMaterials.GOLD, 2, -3.6F, 4, new Item.Settings()), ItemGroups.COMBAT); - Item DIAMOND_POLEARM = register("diamond_polearm", new PolearmItem(ToolMaterials.DIAMOND, 2, -3.6F, 5, new Item.Settings()), ItemGroups.COMBAT); - Item NETHERITE_POLEARM = register("netherite_polearm", new PolearmItem(ToolMaterials.NETHERITE, 2, -3.6F, 5, new Item.Settings().fireproof()), ItemGroups.COMBAT); + Item WOODEN_POLEARM = register("wooden_polearm", new PolearmItem(ToolMaterials.WOOD, 2, -3.2F, 2, new Item.Settings()), ItemGroups.COMBAT); + Item STONE_POLEARM = register("stone_polearm", new PolearmItem(ToolMaterials.STONE, 2, -3.2F, 2, new Item.Settings()), ItemGroups.COMBAT); + Item IRON_POLEARM = register("iron_polearm", new PolearmItem(ToolMaterials.IRON, 2, -3.1F, 3, new Item.Settings()), ItemGroups.COMBAT); + Item GOLDEN_POLEARM = register("golden_polearm", new PolearmItem(ToolMaterials.GOLD, 3, -3F, 4, new Item.Settings()), ItemGroups.COMBAT); + Item DIAMOND_POLEARM = register("diamond_polearm", new PolearmItem(ToolMaterials.DIAMOND, 3, -3F, 5, new Item.Settings()), ItemGroups.COMBAT); + Item NETHERITE_POLEARM = register("netherite_polearm", new PolearmItem(ToolMaterials.NETHERITE, 3, -3F, 6, new Item.Settings().fireproof()), ItemGroups.COMBAT); 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); From 17b014939a8f552d02cc102c9525820d22700303 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 18:35:26 +0100 Subject: [PATCH 047/110] Polearms can no longer accept the sweeping enchant. Closes #408 --- .../unicopia/item/PolearmItem.java | 10 ++++++++- .../enchantment/CustomEnchantableItem.java | 8 +++++++ .../unicopia/mixin/MixinEnchantment.java | 21 +++++++++++++++++++ .../mixin/MixinEnchantmentHelper.java | 9 ++++++++ src/main/resources/unicopia.mixin.json | 1 + 5 files changed, 48 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/item/enchantment/CustomEnchantableItem.java create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java diff --git a/src/main/java/com/minelittlepony/unicopia/item/PolearmItem.java b/src/main/java/com/minelittlepony/unicopia/item/PolearmItem.java index 5dc90908..85517dc5 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/PolearmItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/PolearmItem.java @@ -7,14 +7,17 @@ import com.google.common.collect.Multimap; import com.minelittlepony.unicopia.UTags; import com.minelittlepony.unicopia.entity.Living; import com.minelittlepony.unicopia.entity.mob.UEntityAttributes; +import com.minelittlepony.unicopia.item.enchantment.CustomEnchantableItem; import net.minecraft.block.*; +import net.minecraft.enchantment.Enchantment; +import net.minecraft.enchantment.Enchantments; import net.minecraft.entity.EquipmentSlot; import net.minecraft.entity.LivingEntity; import net.minecraft.entity.attribute.*; import net.minecraft.item.*; -public class PolearmItem extends SwordItem { +public class PolearmItem extends SwordItem implements CustomEnchantableItem { static final UUID ATTACK_RANGE_MODIFIER_ID = UUID.fromString("A7B3659C-AA74-469C-963A-09A391DCAA0F"); private final Multimap attributeModifiers; @@ -65,4 +68,9 @@ public class PolearmItem extends SwordItem { return true; } + + @Override + public boolean isAcceptableEnchant(ItemStack stack, Enchantment enchantment) { + return enchantment != Enchantments.SWEEPING; + } } diff --git a/src/main/java/com/minelittlepony/unicopia/item/enchantment/CustomEnchantableItem.java b/src/main/java/com/minelittlepony/unicopia/item/enchantment/CustomEnchantableItem.java new file mode 100644 index 00000000..5fbec700 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/item/enchantment/CustomEnchantableItem.java @@ -0,0 +1,8 @@ +package com.minelittlepony.unicopia.item.enchantment; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.item.ItemStack; + +public interface CustomEnchantableItem { + boolean isAcceptableEnchant(ItemStack stack, Enchantment enchantment); +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java new file mode 100644 index 00000000..5143711c --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java @@ -0,0 +1,21 @@ +package com.minelittlepony.unicopia.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.minelittlepony.unicopia.item.enchantment.CustomEnchantableItem; + +import net.minecraft.enchantment.Enchantment; +import net.minecraft.item.ItemStack; + +@Mixin(Enchantment.class) +abstract class MixinEnchantment { + @Inject(method = "isAcceptableItem", at = @At("HEAD"), cancellable = true) + private void onIsAcceptableItem(ItemStack stack, CallbackInfoReturnable info) { + if (stack.getItem() instanceof CustomEnchantableItem item && !item.isAcceptableEnchant(stack, (Enchantment)(Object)this)) { + info.setReturnValue(false); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java index 4458399c..0dd1aacf 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java @@ -1,5 +1,7 @@ package com.minelittlepony.unicopia.mixin; +import java.util.List; + import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -9,7 +11,9 @@ import com.minelittlepony.unicopia.entity.player.Pony; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.enchantment.EnchantmentLevelEntry; import net.minecraft.entity.LivingEntity; +import net.minecraft.item.ItemStack; @Mixin(EnchantmentHelper.class) abstract class MixinEnchantmentHelper { @@ -23,4 +27,9 @@ abstract class MixinEnchantmentHelper { } }); } + + @Inject(method = "getPossibleEntries", at = @At("RETURN")) + private static void onGetPossibleEntries(int power, ItemStack stack, boolean treasureAllowed, CallbackInfoReturnable> info) { + info.getReturnValue().removeIf(entry -> !entry.enchantment.isAcceptableItem(stack)); + } } diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 17bd2121..be3b67d5 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -17,6 +17,7 @@ "MixinChunkBlockLightProvider", "MutableBlockLightStorage", "MixinDamageSource", + "MixinEnchantment", "MixinEnchantmentHelper", "MixinFallLocation", "MixinEntity", From a987e9612a5352de50ad5a88a669453b06c6682f Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 24 Sep 2024 23:49:09 +0100 Subject: [PATCH 048/110] - Fixed clouds affecting lighting - Clouds no longer affect the world heightmap (fixes certain structures generating on clouds) - Added proper cloud gen beyond just structures - Fixed mobs spawning on clouds when they shouldn't --- .../block/cloud/NaturalCloudBlock.java | 18 ++- .../unicopia/mixin/MixinHeightmap.java | 21 +++ .../unicopia/server/world/UWorldGen.java | 8 + .../server/world/gen/CloudCarver.java | 142 ++++++++++++++++++ .../overworld_cloud_carver.json | 26 ++++ src/main/resources/unicopia.mixin.json | 1 + 6 files changed, 215 insertions(+), 1 deletion(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/MixinHeightmap.java create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java create mode 100644 src/main/resources/data/unicopia/worldgen/configured_carver/overworld_cloud_carver.json diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java index 2d7325dc..cc176942 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java @@ -6,6 +6,8 @@ import org.jetbrains.annotations.Nullable; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.registry.tag.ItemTags; @@ -16,6 +18,7 @@ import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.BlockView; import net.minecraft.world.World; public class NaturalCloudBlock extends PoreousCloudBlock { @@ -25,10 +28,23 @@ public class NaturalCloudBlock extends PoreousCloudBlock { public NaturalCloudBlock(Settings settings, boolean meltable, @Nullable Supplier soggyBlock, Supplier compactedBlock) { - super(settings.nonOpaque(), meltable, soggyBlock); + super(settings.nonOpaque().allowsSpawning((state, world, pos, type) -> { + return type == EntityType.PHANTOM || type == EntityType.PARROT || type.getSpawnGroup() == SpawnGroup.AMBIENT; + }), meltable, soggyBlock); this.compactedBlock = compactedBlock; } + @Override + @Deprecated + public float getAmbientOcclusionLightLevel(BlockState state, BlockView world, BlockPos pos) { + return 0.9F; + } + + @Override + public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) { + return true; + } + @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { ItemStack stack = player.getStackInHand(hand); diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinHeightmap.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinHeightmap.java new file mode 100644 index 00000000..99da4dde --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinHeightmap.java @@ -0,0 +1,21 @@ +package com.minelittlepony.unicopia.mixin; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + +import com.minelittlepony.unicopia.block.cloud.CloudLike; + +import net.minecraft.block.BlockState; +import net.minecraft.world.Heightmap; + +@Mixin(Heightmap.class) +abstract class MixinHeightmap { + @Inject(method = "method_16682", at = @At("HEAD"), cancellable = true) + private static void excludeCloudsFromWorldSurfaceHeightMap(BlockState state, CallbackInfoReturnable info) { + if (state.getBlock() instanceof CloudLike) { + info.setReturnValue(false); + } + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java index 5100d075..2c8d1903 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java @@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.block.ShellsBlock; import com.minelittlepony.unicopia.block.UBlocks; import com.minelittlepony.unicopia.server.world.gen.CaveCarvingStructureProcessor; +import com.minelittlepony.unicopia.server.world.gen.CloudCarver; import com.minelittlepony.unicopia.server.world.gen.OverworldBiomeSelectionCallback; import com.minelittlepony.unicopia.server.world.gen.SurfaceGrowthStructureProcessor; import com.minelittlepony.unicopia.util.registry.DynamicRegistry; @@ -38,6 +39,9 @@ import net.minecraft.world.biome.OverworldBiomeCreator; import net.minecraft.world.biome.SpawnSettings; import net.minecraft.world.gen.GenerationStep; import net.minecraft.world.gen.blockpredicate.BlockPredicate; +import net.minecraft.world.gen.carver.Carver; +import net.minecraft.world.gen.carver.CaveCarverConfig; +import net.minecraft.world.gen.carver.ConfiguredCarver; import net.minecraft.world.gen.feature.ConfiguredFeatures; import net.minecraft.world.gen.feature.DefaultBiomeFeatures; import net.minecraft.world.gen.feature.Feature; @@ -126,6 +130,9 @@ public interface UWorldGen { StructureProcessorType SURFACE_GROWTH_STRUCTURE_PROCESSOR = Registry.register(Registries.STRUCTURE_PROCESSOR, Unicopia.id("surface_growth"), () -> SurfaceGrowthStructureProcessor.CODEC); StructureProcessorType CAVE_CARVING_STRUCTURE_PROCESSOR = Registry.register(Registries.STRUCTURE_PROCESSOR, Unicopia.id("cave_carving"), () -> CaveCarvingStructureProcessor.CODEC); + RegistryKey> OVERWORLD_CLOUD_CARVER_CONFIG = RegistryKey.of(RegistryKeys.CONFIGURED_CARVER, Unicopia.id("overworld_cloud_carver")); + Carver CLOUR_CARVER = Registry.register(Registries.CARVER, Unicopia.id("cloud"), new CloudCarver(CaveCarverConfig.CAVE_CODEC)); + @SafeVarargs static T applyAll(T t, Consumer ...consumers) { for (Consumer consumer : consumers) { @@ -142,6 +149,7 @@ public interface UWorldGen { .or(BiomeSelectors.tag(BiomeTags.IS_RIVER)) .or(BiomeSelectors.includeByKey(BiomeKeys.STONY_SHORE)) ), GenerationStep.Feature.VEGETAL_DECORATION, SHELLS_PLACED_FEATURE); + BiomeModifications.addCarver(BiomeSelectors.foundInOverworld(), GenerationStep.Carver.AIR, OVERWORLD_CLOUD_CARVER_CONFIG); UTreeGen.bootstrap(); OverworldBiomeSelectionCallback.EVENT.register(context -> { diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java new file mode 100644 index 00000000..21356298 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java @@ -0,0 +1,142 @@ +package com.minelittlepony.unicopia.server.world.gen; + +import java.util.function.Function; + +import com.minelittlepony.unicopia.block.UBlocks; +import com.mojang.serialization.Codec; +import net.minecraft.block.BlockState; +import net.minecraft.registry.entry.RegistryEntry; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.random.Random; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.gen.carver.Carver; +import net.minecraft.world.gen.carver.CarverContext; +import net.minecraft.world.gen.carver.CarvingMask; +import net.minecraft.world.gen.carver.CaveCarver; +import net.minecraft.world.gen.carver.CaveCarverConfig; +import net.minecraft.world.gen.chunk.AquiferSampler; +import net.minecraft.world.gen.densityfunction.DensityFunction.NoisePos; + +public class CloudCarver extends CaveCarver { + + private Random random; + + public CloudCarver(Codec codec) { + super(codec); + } + + @Override + protected int getMaxCaveCount() { + return 15; + } + + @Override + protected float getTunnelSystemWidth(Random random) { + return (random.nextFloat() * 2.0F + random.nextFloat()) * 2.0F; + } + + @Override + protected double getTunnelSystemHeightWidthRatio() { + return 0.5; + } + + @Override + public boolean carve( + CarverContext context, + CaveCarverConfig config, + Chunk chunk, + Function> function, + Random random, + AquiferSampler sampler, + ChunkPos chunkPos, + CarvingMask carvingMask + ) { + this.random = random; + return super.carve(context, config, chunk, function, random, new AquiferSampler() { + @Override + public BlockState apply(NoisePos pos, double density) { + BlockState state = sampler.apply(pos, density); + return state != null && state.isAir() ? UBlocks.CLOUD.getDefaultState() : state; + } + + @Override + public boolean needsFluidTick() { + return sampler.needsFluidTick(); + } + + }, chunkPos, carvingMask); + } + + @Override + protected void carveCave( + CarverContext context, + CaveCarverConfig config, + Chunk chunk, + Function> posToBiome, + AquiferSampler aquiferSampler, + double x, + double y, + double z, + float xScale, + double yScale, + CarvingMask mask, + Carver.SkipPredicate skipPredicate + ) { + if (random == null) { + return; + } + int maxY = context.getMinY() + context.getHeight(); + + int bubbleCount = 10 + random.nextInt(12); + for (int i = 0; i < bubbleCount; i++) { + double width = 1.5 * xScale + random.nextTriangular(3, 2); + double height = Math.min(width * yScale * (1 + random.nextFloat() * 2) + MathHelper.sin((float) (Math.PI / 2)) * xScale, maxY - y); + double bubbleX = x + (random.nextFloat() * 2 - 1) * width; + double bubbleZ = z + (random.nextFloat() * 2 - 1) * width; + carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX + 1.0, y, bubbleZ, width, height, mask, skipPredicate); + } + } + + @Override + protected void carveTunnels( + CarverContext context, + CaveCarverConfig config, + Chunk chunk, + Function> posToBiome, + long seed, + AquiferSampler aquiferSampler, + double x, + double y, + double z, + double horizontalScale, + double verticalScale, + float w, + float yaw, + float pitch, + int branchStartIndex, + int branchCount, + double yawPitchRatio, + CarvingMask mask, + Carver.SkipPredicate skipPredicate + ) { + if (random == null) { + return; + } + int maxY = context.getMinY() + context.getHeight(); + int bubbleCount = 10 + random.nextInt(12); + for (int i = 0; i < bubbleCount; i++) { + double width = /*1.5 + MathHelper.sin((float) (Math.PI / 2)) * xScale +*/ 1.5 * horizontalScale + random.nextInt(3) + w; + double height = width * (1 + random.nextFloat() * 2) * verticalScale * 0.2; + double bubbleX = x + (random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleZ = z + (random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleY = y + random.nextFloat() * height * 0.5; + if (bubbleY + height < maxY) { + carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX, bubbleY, bubbleZ, width, height, mask, skipPredicate); + } + } + //super.carveTunnels(context, config, chunk, posToBiome, seed, aquiferSampler, x, y, z, horizontalScale, verticalScale, w, yaw, pitch, branchStartIndex, branchCount, yawPitchRatio, mask, skipPredicate); + } +} \ No newline at end of file diff --git a/src/main/resources/data/unicopia/worldgen/configured_carver/overworld_cloud_carver.json b/src/main/resources/data/unicopia/worldgen/configured_carver/overworld_cloud_carver.json new file mode 100644 index 00000000..b7543372 --- /dev/null +++ b/src/main/resources/data/unicopia/worldgen/configured_carver/overworld_cloud_carver.json @@ -0,0 +1,26 @@ +{ + "type": "unicopia:cloud", + "config": { + "probability": 0.05, + "y": { + "type": "minecraft:uniform", + "min_inclusive": { + "absolute": 240 + }, + "max_inclusive": { + "absolute": 600 + } + }, + "yScale": 0.15, + "lava_level": { + "above_bottom": 8 + }, + "replaceable": "minecraft:air", + "horizontal_radius_multiplier": 3.7, + "vertical_radius_multiplier": 2.8, + "floor_level": { + "type": "minecraft:constant", + "value": 0 + } + } +} diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index be3b67d5..3079ef57 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -28,6 +28,7 @@ "MixinFallingBlockEntity", "MixinFlowableFluid", "MixinGuardianTargetPredicate", + "MixinHeightmap", "MixinItem", "MixinItemEntity", "MixinItemStack", From c32bf4c0993c5db6cbee5a24d7d692df3aa47b87 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 25 Sep 2024 19:41:50 +0100 Subject: [PATCH 049/110] Tweak the cloud carver to set the top layer to soggy clouds --- .../unicopia/block/cloud/CloudBedBlock.java | 2 +- .../unicopia/block/cloud/CloudBlock.java | 13 +++++- .../unicopia/block/cloud/CloudChestBlock.java | 2 +- .../unicopia/block/cloud/CloudDoorBlock.java | 2 +- .../unicopia/block/cloud/CloudLike.java | 10 ++++- .../block/cloud/CloudStairsBlock.java | 13 +++++- .../block/cloud/NaturalCloudBlock.java | 18 +------- .../unicopia/block/cloud/Soakable.java | 2 +- .../server/world/gen/CloudCarver.java | 45 ++++++++++++++++++- 9 files changed, 82 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java index e6eb8ddf..5b8f1c69 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java @@ -24,7 +24,7 @@ public class CloudBedBlock extends FancyBedBlock implements CloudLike { private final CloudBlock baseBlock; public CloudBedBlock(String base, BlockState baseState, Settings settings) { - super(base, settings.dynamicBounds()); + super(base, CloudLike.applyCloudProperties(settings)); this.baseState = baseState; this.baseBlock = (CloudBlock)baseState.getBlock(); } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java index 05953dc8..23e0e3f8 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -30,10 +30,21 @@ public class CloudBlock extends Block implements CloudLike { protected final boolean meltable; public CloudBlock(Settings settings, boolean meltable) { - super((meltable ? settings.ticksRandomly() : settings).nonOpaque().dynamicBounds()); + super(CloudLike.applyCloudProperties(meltable ? settings.ticksRandomly() : settings)); this.meltable = meltable; } + @Override + @Deprecated + public float getAmbientOcclusionLightLevel(BlockState state, BlockView world, BlockPos pos) { + return 0.9F; + } + + @Override + public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) { + return true; + } + @Override public void onEntityLand(BlockView world, Entity entity) { boolean bounce = Math.abs(entity.getVelocity().y) > 0.3; diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java index f4f5ba0b..49708712 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java @@ -77,7 +77,7 @@ public class CloudChestBlock extends ChestBlock implements CloudLike { }; public CloudChestBlock(Settings settings, BlockState baseState) { - super(settings.dynamicBounds(), () -> UBlockEntities.CLOUD_CHEST); + super(CloudLike.applyCloudProperties(settings), () -> UBlockEntities.CLOUD_CHEST); this.baseState = baseState; this.baseBlock = (CloudBlock)baseState.getBlock(); } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java index e0b495d1..0e22e7ea 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java @@ -26,7 +26,7 @@ public class CloudDoorBlock extends DoorBlock implements CloudLike { private final CloudBlock baseBlock; public CloudDoorBlock(Settings settings, BlockState baseState, BlockSetType blockSet) { - super(settings.dynamicBounds(), blockSet); + super(CloudLike.applyCloudProperties(settings), blockSet); this.baseState = baseState; this.baseBlock = (CloudBlock)baseState.getBlock(); } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudLike.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudLike.java index ec9ef4fd..3684c890 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudLike.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudLike.java @@ -1,5 +1,13 @@ package com.minelittlepony.unicopia.block.cloud; -public interface CloudLike { +import net.minecraft.block.Block; +import net.minecraft.entity.EntityType; +import net.minecraft.entity.SpawnGroup; +public interface CloudLike { + static Block.Settings applyCloudProperties(Block.Settings settings) { + return settings.nonOpaque().dynamicBounds().allowsSpawning((state, world, pos, type) -> { + return type == EntityType.PHANTOM || type == EntityType.PARROT || type.getSpawnGroup() == SpawnGroup.AMBIENT; + }); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java index a2b1e4ba..5292dd2d 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java @@ -21,10 +21,21 @@ public class CloudStairsBlock extends StairsBlock implements CloudLike { private final CloudBlock baseBlock; public CloudStairsBlock(BlockState baseState, Settings settings) { - super(baseState, settings.dynamicBounds()); + super(baseState, CloudLike.applyCloudProperties(settings)); this.baseBlock = (CloudBlock)baseState.getBlock(); } + @Override + @Deprecated + public float getAmbientOcclusionLightLevel(BlockState state, BlockView world, BlockPos pos) { + return baseBlock.getAmbientOcclusionLightLevel(state, world, pos); + } + + @Override + public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) { + return baseBlock.isTransparent(state, world, pos); + } + @Override public void onEntityLand(BlockView world, Entity entity) { baseBlock.onEntityLand(world, entity); diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java index cc176942..27a569d9 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java @@ -6,8 +6,6 @@ import org.jetbrains.annotations.Nullable; import net.minecraft.block.Block; import net.minecraft.block.BlockState; -import net.minecraft.entity.EntityType; -import net.minecraft.entity.SpawnGroup; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.registry.tag.ItemTags; @@ -18,7 +16,6 @@ import net.minecraft.util.ActionResult; import net.minecraft.util.Hand; import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; -import net.minecraft.world.BlockView; import net.minecraft.world.World; public class NaturalCloudBlock extends PoreousCloudBlock { @@ -28,23 +25,10 @@ public class NaturalCloudBlock extends PoreousCloudBlock { public NaturalCloudBlock(Settings settings, boolean meltable, @Nullable Supplier soggyBlock, Supplier compactedBlock) { - super(settings.nonOpaque().allowsSpawning((state, world, pos, type) -> { - return type == EntityType.PHANTOM || type == EntityType.PARROT || type.getSpawnGroup() == SpawnGroup.AMBIENT; - }), meltable, soggyBlock); + super(settings, meltable, soggyBlock); this.compactedBlock = compactedBlock; } - @Override - @Deprecated - public float getAmbientOcclusionLightLevel(BlockState state, BlockView world, BlockPos pos) { - return 0.9F; - } - - @Override - public boolean isTransparent(BlockState state, BlockView world, BlockPos pos) { - return true; - } - @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { ItemStack stack = player.getStackInHand(hand); diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java index 94ce19e8..d192c71d 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java @@ -78,7 +78,7 @@ public interface Soakable { if (moisture < 7) { world.setBlockState(pos, soakable.getStateWithMoisture(state, moisture + 1)); } - } else { + } else if (!world.isAir(pos.up())) { if (moisture > 1) { BlockPos neighborPos = pos.offset(Util.getRandom(Soakable.DIRECTIONS, random)); BlockState neighborState = world.getBlockState(neighborPos); diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java index 21356298..41736d0d 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java @@ -2,12 +2,18 @@ package com.minelittlepony.unicopia.server.world.gen; import java.util.function.Function; +import org.apache.commons.lang3.mutable.MutableBoolean; + import com.minelittlepony.unicopia.block.UBlocks; import com.mojang.serialization.Codec; + +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; +import it.unimi.dsi.fastutil.longs.LongSet; import net.minecraft.block.BlockState; import net.minecraft.registry.entry.RegistryEntry; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; +import net.minecraft.util.math.Direction; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.random.Random; import net.minecraft.world.biome.Biome; @@ -24,6 +30,8 @@ public class CloudCarver extends CaveCarver { private Random random; + private final LongSet topWrittenPositions = new LongOpenHashSet(); + public CloudCarver(Codec codec) { super(codec); } @@ -55,7 +63,7 @@ public class CloudCarver extends CaveCarver { CarvingMask carvingMask ) { this.random = random; - return super.carve(context, config, chunk, function, random, new AquiferSampler() { + boolean result = super.carve(context, config, chunk, function, random, new AquiferSampler() { @Override public BlockState apply(NoisePos pos, double density) { BlockState state = sampler.apply(pos, density); @@ -68,6 +76,12 @@ public class CloudCarver extends CaveCarver { } }, chunkPos, carvingMask); + BlockPos.Mutable mutable = new BlockPos.Mutable(); + topWrittenPositions.forEach(l -> { + processSurfaceBlocks(mutable.set(l), context, config, chunk, random); + }); + topWrittenPositions.clear(); + return result; } @Override @@ -139,4 +153,33 @@ public class CloudCarver extends CaveCarver { } //super.carveTunnels(context, config, chunk, posToBiome, seed, aquiferSampler, x, y, z, horizontalScale, verticalScale, w, yaw, pitch, branchStartIndex, branchCount, yawPitchRatio, mask, skipPredicate); } + + @Override + protected boolean carveAtPoint( + CarverContext context, + CaveCarverConfig config, + Chunk chunk, + Function> posToBiome, + CarvingMask mask, + BlockPos.Mutable pos, + BlockPos.Mutable tmp, + AquiferSampler aquiferSampler, + MutableBoolean replacedGrassy + ) { + if (super.carveAtPoint(context, config, chunk, posToBiome, mask, pos, tmp, aquiferSampler, replacedGrassy)) { + topWrittenPositions.remove(tmp.set(pos).move(Direction.DOWN).asLong()); + topWrittenPositions.add(pos.asLong()); + if (chunk.getBlockState(tmp).isOf(UBlocks.SOGGY_CLOUD)) { + chunk.setBlockState(tmp, UBlocks.CLOUD.getDefaultState(), false); + } + return true; + } + return false; + } + + protected void processSurfaceBlocks(BlockPos.Mutable pos, CarverContext context, CaveCarverConfig config, Chunk chunk, Random random) { + if (chunk.getBlockState(pos.move(Direction.UP)).isAir()) { + chunk.setBlockState(pos.move(Direction.DOWN), UBlocks.SOGGY_CLOUD.getDefaultState(), false); + } + } } \ No newline at end of file From 4cfb8d835f9f71b26574e47646da9930edc88852 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 25 Sep 2024 19:42:10 +0100 Subject: [PATCH 050/110] Mobs with feather falling 4 boots can now properly walk on clouds --- src/main/java/com/minelittlepony/unicopia/EquineContext.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/EquineContext.java b/src/main/java/com/minelittlepony/unicopia/EquineContext.java index 596c2cbb..824940de 100644 --- a/src/main/java/com/minelittlepony/unicopia/EquineContext.java +++ b/src/main/java/com/minelittlepony/unicopia/EquineContext.java @@ -22,7 +22,7 @@ public interface EquineContext { } default boolean collidesWithClouds() { - return getCompositeRace().canInteractWithClouds(); + return getCompositeRace().canInteractWithClouds() || getCloudWalkingStrength() >= 1; } default boolean hasFeatherTouch() { From 4f4ac3f8095082a56153c3d29f4c34dbd14eea9c Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 25 Sep 2024 20:34:53 +0100 Subject: [PATCH 051/110] Mobs with feather falling 4 boots can now walk and pathfind on clouds --- .../unicopia/InteractionManager.java | 17 +++++++++--- .../unicopia/block/cloud/CloudBedBlock.java | 2 +- .../unicopia/block/cloud/CloudBlock.java | 4 ++- .../unicopia/block/cloud/CloudChestBlock.java | 3 ++- .../unicopia/block/cloud/CloudDoorBlock.java | 8 ++++++ .../block/cloud/CloudStairsBlock.java | 2 +- .../mixin/server/MixinPathNodeMaker.java | 26 +++++++++++++++++++ .../mixin/server/MixinPlayerManager.java | 2 +- src/main/resources/unicopia.mixin.json | 1 + 9 files changed, 57 insertions(+), 8 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPathNodeMaker.java diff --git a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java index 5326ce75..b3fb38b8 100644 --- a/src/main/java/com/minelittlepony/unicopia/InteractionManager.java +++ b/src/main/java/com/minelittlepony/unicopia/InteractionManager.java @@ -2,6 +2,7 @@ package com.minelittlepony.unicopia; import java.util.Map; import java.util.Optional; +import java.util.Stack; import java.util.UUID; import org.jetbrains.annotations.NotNull; @@ -37,7 +38,7 @@ public class InteractionManager { @Nullable private SyncedConfig config; - private EquineContext equineContext = EquineContext.ABSENT; + private final Stack equineContext = new Stack<>(); public static InteractionManager getInstance() { return INSTANCE; @@ -109,11 +110,21 @@ public class InteractionManager { } public void setEquineContext(EquineContext context) { - equineContext = context; + equineContext.push(context); + } + + public void clearEquineContext() { + if (!equineContext.isEmpty()) { + equineContext.pop(); + } } public EquineContext getEquineContext() { - return getClientPony().map(EquineContext.class::cast).orElse(equineContext); + return getClientPony().map(EquineContext.class::cast).orElseGet(this::getPathingEquineContext); + } + + public EquineContext getPathingEquineContext() { + return equineContext.isEmpty() ? EquineContext.ABSENT : equineContext.peek(); } public Optional getClientPony() { diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java index 5b8f1c69..e4d562c3 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBedBlock.java @@ -75,6 +75,6 @@ public class CloudBedBlock extends FancyBedBlock implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - return true; + return baseState.canPathfindThrough(world, pos, type); } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java index 23e0e3f8..6381eda2 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.block.cloud; import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.EquineContext; +import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.entity.player.Pony; import net.minecraft.block.Block; @@ -173,7 +174,8 @@ public class CloudBlock extends Block implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - return true; + System.out.println(InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds()); + return type != NavigationType.LAND || !InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds(); } protected VoxelShape getOutlineShape(BlockState state, BlockView world, BlockPos pos, ShapeContext context, EquineContext equineContext) { diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java index 49708712..7d53232c 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudChestBlock.java @@ -5,6 +5,7 @@ import java.util.Optional; import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.EquineContext; +import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.block.UBlockEntities; import net.minecraft.block.BlockState; import net.minecraft.block.ChestBlock; @@ -139,7 +140,7 @@ public class CloudChestBlock extends ChestBlock implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - return true; + return type != NavigationType.LAND || !InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds(); } public static class TileData extends ChestBlockEntity { diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java index 0e22e7ea..b243a67f 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudDoorBlock.java @@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.block.cloud; import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.EquineContext; +import com.minelittlepony.unicopia.InteractionManager; import com.minelittlepony.unicopia.Race; import net.minecraft.block.BlockSetType; @@ -10,6 +11,7 @@ import net.minecraft.block.BlockState; import net.minecraft.block.DoorBlock; import net.minecraft.block.ShapeContext; import net.minecraft.entity.Entity; +import net.minecraft.entity.ai.pathing.NavigationType; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemPlacementContext; import net.minecraft.util.ActionResult; @@ -84,4 +86,10 @@ public class CloudDoorBlock extends DoorBlock implements CloudLike { entity.setVelocity(entity.getVelocity().multiply(0.5F, 1, 0.5F)); } } + + @Override + @Deprecated + public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { + return !InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds() || super.canPathfindThrough(state, world, pos, type); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java index 5292dd2d..dcff5ff1 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudStairsBlock.java @@ -97,6 +97,6 @@ public class CloudStairsBlock extends StairsBlock implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - return true; + return baseBlock.canPathfindThrough(state, world, pos, type); } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPathNodeMaker.java b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPathNodeMaker.java new file mode 100644 index 00000000..9e18310c --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPathNodeMaker.java @@ -0,0 +1,26 @@ +package com.minelittlepony.unicopia.mixin.server; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.minelittlepony.unicopia.EquineContext; +import com.minelittlepony.unicopia.InteractionManager; + +import net.minecraft.entity.ai.pathing.PathNodeMaker; +import net.minecraft.entity.mob.MobEntity; +import net.minecraft.world.chunk.ChunkCache; + +@Mixin(PathNodeMaker.class) +abstract class MixinPathNodeMaker { + @Inject(method = "init", at = @At("HEAD")) + private void onInit(ChunkCache cachedWorld, MobEntity entity, CallbackInfo info) { + InteractionManager.getInstance().setEquineContext(EquineContext.of(entity)); + } + + @Inject(method = "clear", at = @At("HEAD")) + private void onClear(CallbackInfo info) { + InteractionManager.getInstance().clearEquineContext(); + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPlayerManager.java b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPlayerManager.java index 0c845c1c..271bf40a 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPlayerManager.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/server/MixinPlayerManager.java @@ -44,6 +44,6 @@ abstract class MixinPlayerManager { @Inject(method = "respawnPlayer", at = @At("RETURN")) private void afterRespawnPlayer(ServerPlayerEntity player, boolean alive, CallbackInfoReturnable info) { - InteractionManager.getInstance().setEquineContext(EquineContext.ABSENT); + InteractionManager.getInstance().clearEquineContext(); } } diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 3079ef57..533483c0 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -54,6 +54,7 @@ "MixinWorld", "PointOfInterestTypesAccessor", "server.MixinEntityTrackerEntry", + "server.MixinPathNodeMaker", "server.MixinPlayerManager", "server.MixinServerPlayerEntity", "server.MixinServerPlayNetworkHandler", From 2b979d4fe4b19198394640fbe25f7ef0abb74e19 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 25 Sep 2024 20:47:23 +0100 Subject: [PATCH 052/110] Skip applying the saturation shader if it's not required and remove unneccessary GL actions. Maybe Fixes #445 --- .../client/render/shader/ViewportShader.java | 27 ++++++------------- 1 file changed, 8 insertions(+), 19 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java b/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java index 21df38bc..0bda2eb9 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java +++ b/src/main/java/com/minelittlepony/unicopia/client/render/shader/ViewportShader.java @@ -9,7 +9,6 @@ import com.google.common.collect.*; import com.google.gson.JsonSyntaxException; import com.minelittlepony.unicopia.Unicopia; import com.minelittlepony.unicopia.entity.player.Pony; -import com.mojang.blaze3d.systems.RenderSystem; import com.mojang.logging.LogUtils; import it.unimi.dsi.fastutil.objects.Object2FloatMap; @@ -52,11 +51,7 @@ public class ViewportShader implements SynchronousResourceReloader, Identifiable } } - if (shaderId == null) { - return; - } - - if (Unicopia.getConfig().disableShaders.get()) { + if (shaderId == null || Unicopia.getConfig().disableShaders.get()) { return; } @@ -81,29 +76,23 @@ public class ViewportShader implements SynchronousResourceReloader, Identifiable } if (shader != null && client.player != null) { - RenderSystem.disableBlend(); - RenderSystem.disableDepthTest(); - RenderSystem.resetTextureMatrix(); - Pony pony = Pony.of(client.player); float corruption = pony.getCorruption().getScaled(0.9F); - corruption = pony.getInterpolator().interpolate("corruption", corruption, 10); + if (!MathHelper.approximatelyEquals(corruption, 0)) { + corruption = pony.getInterpolator().interpolate("corruption", corruption, 10); - corruption = 1 - corruption + 0.05F; + corruption = 1 - corruption + 0.05F; - shader.setUniformValue("color_convolve", "Saturation", corruption); - shader.render(tickDelta); + shader.setUniformValue("color_convolve", "Saturation", corruption); + shader.render(tickDelta); + } } } @Override public void reload(ResourceManager var1) { - if (shader != null) { - loadShader(shader.id); - } else { - loadShader(DESATURATION_SHADER); - } + loadShader(shader != null ? shader.id : DESATURATION_SHADER); } static class LoadedShader extends PostEffectProcessor { From 62679897b2b9c86e4102234d57bc82cb85ddcf57 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 29 Sep 2024 00:40:30 +0100 Subject: [PATCH 053/110] Allow making earth pony morph using pebbles --- .../com/minelittlepony/unicopia/entity/effect/UPotions.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java b/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java index 2fb07320..5709ba23 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java @@ -20,9 +20,9 @@ import net.minecraft.util.Identifier; import net.minecraft.registry.Registries; public interface UPotions { - MorphingPotion MORPH_EARTH_PONY = new MorphingPotion(Race.EARTH).registerBaseRecipes(Potions.STRENGTH, UItems.CURING_JOKE); - MorphingPotion MORPH_UNICORN = new MorphingPotion(Race.UNICORN).registerBaseRecipes(Potions.REGENERATION, UItems.BOTCHED_GEM); - MorphingPotion MORPH_PEGASUS = new MorphingPotion(Race.PEGASUS).registerBaseRecipes(Potions.SWIFTNESS, UItems.PEGASUS_FEATHER, UItems.HIPPOGRIFF_BADGE, Items.FEATHER); + MorphingPotion MORPH_EARTH_PONY = new MorphingPotion(Race.EARTH).registerBaseRecipes(Potions.STRENGTH, UItems.CURING_JOKE, UItems.PEBBLES); + MorphingPotion MORPH_UNICORN = new MorphingPotion(Race.UNICORN).registerBaseRecipes(Potions.REGENERATION, UItems.BOTCHED_GEM, UItems.GEMSTONE); + MorphingPotion MORPH_PEGASUS = new MorphingPotion(Race.PEGASUS).registerBaseRecipes(Potions.SWIFTNESS, UItems.PEGASUS_FEATHER, UItems.GRYPHON_FEATHER, Items.FEATHER); MorphingPotion MORPH_BAT = new MorphingPotion(Race.BAT).registerBaseRecipes(Potions.NIGHT_VISION, UItems.BUTTERFLY); MorphingPotion MORPH_CHANGELING = new MorphingPotion(Race.CHANGELING).registerBaseRecipes(Potions.HARMING, UItems.CARAPACE); MorphingPotion MORPH_KIRIN = new MorphingPotion(Race.KIRIN).registerBaseRecipes(Potions.FIRE_RESISTANCE, Items.MAGMA_CREAM); From c0d920010103a1ea94d5c6bc45779f06a03c1c21 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 29 Sep 2024 00:40:50 +0100 Subject: [PATCH 054/110] Allow making changeling morph using rotten apples --- .../com/minelittlepony/unicopia/entity/effect/UPotions.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java b/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java index 5709ba23..ed9c57c4 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java @@ -24,7 +24,7 @@ public interface UPotions { MorphingPotion MORPH_UNICORN = new MorphingPotion(Race.UNICORN).registerBaseRecipes(Potions.REGENERATION, UItems.BOTCHED_GEM, UItems.GEMSTONE); MorphingPotion MORPH_PEGASUS = new MorphingPotion(Race.PEGASUS).registerBaseRecipes(Potions.SWIFTNESS, UItems.PEGASUS_FEATHER, UItems.GRYPHON_FEATHER, Items.FEATHER); MorphingPotion MORPH_BAT = new MorphingPotion(Race.BAT).registerBaseRecipes(Potions.NIGHT_VISION, UItems.BUTTERFLY); - MorphingPotion MORPH_CHANGELING = new MorphingPotion(Race.CHANGELING).registerBaseRecipes(Potions.HARMING, UItems.CARAPACE); + MorphingPotion MORPH_CHANGELING = new MorphingPotion(Race.CHANGELING).registerBaseRecipes(Potions.HARMING, UItems.CARAPACE, UItems.ROTTEN_APPLE); MorphingPotion MORPH_KIRIN = new MorphingPotion(Race.KIRIN).registerBaseRecipes(Potions.FIRE_RESISTANCE, Items.MAGMA_CREAM); MorphingPotion MORPH_HIPPOGRIFF = new MorphingPotion(Race.HIPPOGRIFF).registerBaseRecipes(Potions.WATER_BREATHING, UItems.CLAM_SHELL, UItems.TURRET_SHELL, UItems.SCALLOP_SHELL); From 68820924bf94f1cdb306090de07d6508b03638fd Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 29 Sep 2024 04:28:22 +0100 Subject: [PATCH 055/110] Rain no longer appears above clouds (mostly) --- .../unicopia/client/UnicopiaClient.java | 43 +++------ .../unicopia/entity/player/PlayerPhysics.java | 2 +- .../unicopia/mixin/MixinWorld.java | 40 ++++++++- .../mixin/client/MixinWorldRenderer.java | 14 +++ .../unicopia/server/world/WeatherAccess.java | 89 +++++++++++++++++++ .../server/world/WeatherConditions.java | 30 +++---- 6 files changed, 168 insertions(+), 50 deletions(-) create mode 100644 src/main/java/com/minelittlepony/unicopia/server/world/WeatherAccess.java diff --git a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java index 1ad3f0a1..4e2a8ac4 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java +++ b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java @@ -21,7 +21,6 @@ import com.minelittlepony.unicopia.container.*; import com.minelittlepony.unicopia.entity.player.PlayerCamera; import com.minelittlepony.unicopia.entity.player.Pony; import com.minelittlepony.unicopia.network.handler.ClientNetworkHandlerImpl; -import com.minelittlepony.unicopia.server.world.WeatherConditions; import com.minelittlepony.unicopia.server.world.ZapAppleStageStore; import com.minelittlepony.unicopia.util.Lerp; @@ -38,7 +37,6 @@ import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.resource.ResourceType; import net.minecraft.text.Text; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; @@ -55,9 +53,8 @@ public class UnicopiaClient implements ClientModInitializer { return Pony.of(MinecraftClient.getInstance().player); } - @Nullable - private Float originalRainGradient; private final Lerp rainGradient = new Lerp(0); + private final Lerp thunderGradient = new Lerp(0); public final Lerp tangentalSkyAngle = new Lerp(0, true); public final Lerp skyAngle = new Lerp(0, true); @@ -157,38 +154,22 @@ public class UnicopiaClient implements ClientModInitializer { } private void onWorldTick(ClientWorld world) { - BlockPos pos = MinecraftClient.getInstance().getCameraEntity().getBlockPos(); + /*BlockPos pos = MinecraftClient.getInstance().getCameraEntity().getBlockPos(); float tickDelta = MinecraftClient.getInstance().getTickDelta(); - Float targetRainGradient = getTargetRainGradient(world, pos, tickDelta); + Float targetRainGradient = ((WeatherAccess)world).isInRangeOfStorm(pos) ? (Float)1F : ((WeatherAccess)world).isBelowCloudLayer(pos) ? null : (Float)0F; + Float targetThunderGradient = ((WeatherAccess)world).isInRangeOfStorm(pos) ? (Float)1F : null; - if (targetRainGradient != null) { - rainGradient.update(targetRainGradient, 2000); - } + ((WeatherAccess)world).setWeatherOverride(null, null); + rainGradient.update(targetRainGradient == null ? world.getRainGradient(tickDelta) : targetRainGradient, 2000); - float gradient = rainGradient.getValue(); - if (!rainGradient.isFinished()) { - world.setRainGradient(gradient); - world.setThunderGradient(gradient); - } - } + ((WeatherAccess)world).setWeatherOverride(1F, null); + thunderGradient.update(targetThunderGradient == null ? world.getThunderGradient(tickDelta) : targetThunderGradient, 2000); - private Float getTargetRainGradient(ClientWorld world, BlockPos pos, float tickDelta) { - if (WeatherConditions.get(world).isInRangeOfStorm(pos)) { - if (originalRainGradient == null) { - originalRainGradient = world.getRainGradient(tickDelta); - } - - return 1F; - } - - if (originalRainGradient != null) { - Float f = originalRainGradient; - originalRainGradient = null; - return f; - } - - return null; + ((WeatherAccess)world).setWeatherOverride( + rainGradient.isFinished() ? targetRainGradient : (Float)rainGradient.getValue(), + thunderGradient.isFinished() ? targetThunderGradient : (Float)thunderGradient.getValue() + );*/ } private void onScreenInit(Screen screen, ButtonList buttons) { diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java index 01850b5b..568e1331 100644 --- a/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java +++ b/src/main/java/com/minelittlepony/unicopia/entity/player/PlayerPhysics.java @@ -690,7 +690,7 @@ public class PlayerPhysics extends EntityPhysics implements Tickab if (entity.getWorld().hasRain(entity.getBlockPos())) { applyTurbulance(velocity); } else { - float targetUpdraft = (float)WeatherConditions.getUpdraft(new BlockPos.Mutable().set(entity.getBlockPos()), entity.getWorld()) / 3F; + float targetUpdraft = WeatherConditions.THERMAL_FIELD.getValue(entity.getWorld(), new BlockPos.Mutable().set(entity.getBlockPos())) / 3F; targetUpdraft *= 1 + motion; if (isGravityNegative()) { targetUpdraft *= -1; diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java index 99ca9150..f0377bb4 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinWorld.java @@ -1,21 +1,32 @@ package com.minelittlepony.unicopia.mixin; import java.util.function.Supplier; + +import org.jetbrains.annotations.Nullable; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; + import com.minelittlepony.unicopia.entity.duck.RotatedView; import com.minelittlepony.unicopia.server.world.BlockDestructionManager; +import com.minelittlepony.unicopia.server.world.WeatherAccess; + import net.minecraft.entity.Entity; +import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; import net.minecraft.world.WorldAccess; @Mixin(World.class) -abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source, RotatedView { - +abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source, RotatedView, WeatherAccess { private final Supplier destructions = BlockDestructionManager.create((World)(Object)this); + @Nullable + private Float rainGradientOverride; + @Nullable + private Float thunderGradientOverride; + private boolean mirrorEntityStatuses; @Override @@ -28,11 +39,36 @@ abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source return destructions.get(); } + @Override + public void setWeatherOverride(Float rain, Float thunder) { + rainGradientOverride = rain; + thunderGradientOverride = thunder; + } + @Inject(method = "sendEntityStatus(Lnet/minecraft/entity/Entity;B)V", at = @At("HEAD")) private void onSendEntityStatus(Entity entity, byte status, CallbackInfo info) { if (mirrorEntityStatuses) { entity.handleStatus(status); } } + + @Inject(method = "getThunderGradient", at = @At("HEAD"), cancellable = true) + private void onGetThunderGradient(float delta, CallbackInfoReturnable info) { + if (thunderGradientOverride != null) { + info.setReturnValue(thunderGradientOverride * ((World)(Object)this).getRainGradient(delta)); + } + } + + @Inject(method = "getRainGradient", at = @At("HEAD"), cancellable = true) + private void onGetRainGradient(float delta, CallbackInfoReturnable info) { + if (rainGradientOverride != null) { + info.setReturnValue(rainGradientOverride); + } + } + + @Inject(method = "hasRain", at = @At("RETURN"), cancellable = true) + private void onHasRain(BlockPos pos, CallbackInfoReturnable info) { + info.setReturnValue((info.getReturnValue() && isBelowCloudLayer(pos)) || isInRangeOfStorm(pos)); + } } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinWorldRenderer.java b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinWorldRenderer.java index edcc852d..4dcaf112 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinWorldRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinWorldRenderer.java @@ -15,6 +15,8 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import com.minelittlepony.unicopia.client.ClientBlockDestructionManager; import com.minelittlepony.unicopia.client.UnicopiaClient; +import com.minelittlepony.unicopia.server.world.WeatherAccess; + import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import net.minecraft.client.render.BlockBreakingInfo; import net.minecraft.client.render.Camera; @@ -22,7 +24,10 @@ import net.minecraft.client.render.WorldRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.client.world.ClientWorld; import net.minecraft.resource.SynchronousResourceReloader; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RotationAxis; +import net.minecraft.world.biome.Biome; +import net.minecraft.world.biome.Biome.Precipitation; @Mixin(value = WorldRenderer.class, priority = 1001) abstract class MixinWorldRenderer implements SynchronousResourceReloader, AutoCloseable, ClientBlockDestructionManager.Source { @@ -80,4 +85,13 @@ abstract class MixinWorldRenderer implements SynchronousResourceReloader, AutoCl matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(UnicopiaClient.getInstance().getSkyAngleDelta(tickDelta))); matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(UnicopiaClient.getInstance().tangentalSkyAngle.getValue())); } + + @Redirect(method = "renderWeather", at = @At(value = "INVOKE", target = "net/minecraft/world/biome/Biome.getPrecipitation(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/world/biome/Biome$Precipitation;")) + private Biome.Precipitation modifyPrecipitation(Biome biome, BlockPos pos) { + Biome.Precipitation precipitation = biome.getPrecipitation(pos); + if (!((WeatherAccess)world).isBelowClientCloudLayer(pos)) { + return Precipitation.NONE; + } + return precipitation; + } } diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/WeatherAccess.java b/src/main/java/com/minelittlepony/unicopia/server/world/WeatherAccess.java new file mode 100644 index 00000000..59f62cd5 --- /dev/null +++ b/src/main/java/com/minelittlepony/unicopia/server/world/WeatherAccess.java @@ -0,0 +1,89 @@ +package com.minelittlepony.unicopia.server.world; + +import com.minelittlepony.unicopia.block.cloud.CloudLike; + +import net.fabricmc.api.EnvType; +import net.fabricmc.api.Environment; +import net.minecraft.client.MinecraftClient; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Direction; +import net.minecraft.util.math.ChunkSectionPos; +import net.minecraft.world.World; +import net.minecraft.world.chunk.Chunk; + +public interface WeatherAccess { + void setWeatherOverride(Float rain, Float thunder); + + default boolean isInRangeOfStorm(BlockPos pos) { + return WeatherConditions.get((World)this).isInRangeOfStorm(pos); + } + + @Environment(EnvType.CLIENT) + default boolean isBelowClientCloudLayer(BlockPos pos) { + + int range = MinecraftClient.isFancyGraphicsOrBetter() ? 10 : 5; + + if (pos.getY() < 230 - range) { + return true; + } + + Chunk chunk = ((World)this).getChunk(pos); + int topSection = chunk.getHighestNonEmptySection(); + + if (topSection > -1) { + int sectionBottomY = ChunkSectionPos.getBlockCoord(topSection); + if (sectionBottomY >= pos.getY() - 16) { + BlockPos.Mutable mutable = pos.mutableCopy(); + BlockPos.Mutable probeMutable = pos.mutableCopy(); + int maxDistance = 16; + + while (((World)this).isInBuildLimit(mutable)) { + if (--maxDistance <= 0) break; + if (!((World)this).isAir(probeMutable.setY(mutable.getY() + range))) { + + mutable.set(pos); + maxDistance = 16; + + while (((World)this).isInBuildLimit(mutable)) { + if (--maxDistance <= 0) break; + if (((World)this).getBlockState(probeMutable.setY(mutable.getY())).getBlock() instanceof CloudLike) { + return false; + } + mutable.move(Direction.DOWN); + } + + return true; + } + mutable.move(Direction.UP); + } + } + } + return false; + } + + default boolean isBelowCloudLayer(BlockPos pos) { + if (pos.getY() < 230) { + return true; + } + + Chunk chunk = ((World)this).getChunk(pos); + int topSection = chunk.getHighestNonEmptySection(); + + if (topSection > -1) { + int sectionBottomY = ChunkSectionPos.getBlockCoord(topSection); + if (sectionBottomY >= pos.getY() - 16) { + BlockPos.Mutable mutable = pos.mutableCopy(); + int maxDistance = 32; + + while (((World)this).isInBuildLimit(mutable)) { + if (--maxDistance <= 0) break; + if (!((World)this).isAir(mutable)) { + return true; + } + mutable.move(Direction.UP); + } + } + } + return false; + } +} diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/WeatherConditions.java b/src/main/java/com/minelittlepony/unicopia/server/world/WeatherConditions.java index 5199f57e..18dd1e9f 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/WeatherConditions.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/WeatherConditions.java @@ -23,8 +23,21 @@ import net.minecraft.world.PersistentState; import net.minecraft.world.World; public class WeatherConditions extends PersistentState implements Tickable { + public static final double FIRE_UPDRAFT = 0.13; + public static final double SAND_UPDRAFT = 0.03; + public static final double SOUL_SAND_UPDRAFT = -0.03; + public static final double ICE_UPDRAFT = 0; + public static final double VOID_UPDRAFT = -0.23; + + public static final float MAX_UPDRAFT_HEIGHT = 20; + public static final float MAX_TERRAIN_HEIGHT = 50; + public static final float MAX_WIND_HEIGHT = 70; + public static final Plane HEIGHT_MAP_FIELD = (world, pos) -> world.getTopY(Type.WORLD_SURFACE_WG, pos.getX(), pos.getZ()); - public static final Plane THERMAL_FIELD = (world, pos) -> (float)getUpdraft(pos, world); + public static final Plane THERMAL_FIELD = (world, pos) -> { + double factor = 1 - getScaledDistanceFromTerrain(pos, world, MAX_UPDRAFT_HEIGHT); + return (float)(factor * getMaterialSurfaceTemperature(pos, world)); + }; public static final Plane LOCAL_ALTITUDE_FIELD = (world, pos) -> { if (!world.isAir(pos)) { return 0; @@ -36,16 +49,6 @@ public class WeatherConditions extends PersistentState implements Tickable { return y - pos.getY(); }; - public static final double FIRE_UPDRAFT = 0.13; - public static final double SAND_UPDRAFT = 0.03; - public static final double SOUL_SAND_UPDRAFT = -0.03; - public static final double ICE_UPDRAFT = 0; - public static final double VOID_UPDRAFT = -0.23; - - public static final float MAX_UPDRAFT_HEIGHT = 20; - public static final float MAX_TERRAIN_HEIGHT = 50; - public static final float MAX_WIND_HEIGHT = 70; - private static final Identifier ID = Unicopia.id("weather_conditions"); public static WeatherConditions get(World world) { @@ -176,11 +179,6 @@ public class WeatherConditions extends PersistentState implements Tickable { .multiply(windFactor); } - public static double getUpdraft(BlockPos.Mutable pos, World world) { - double factor = 1 - getScaledDistanceFromTerrain(pos, world, MAX_UPDRAFT_HEIGHT); - return factor * getMaterialSurfaceTemperature(pos, world); - } - private static float getScaledDistanceFromTerrain(BlockPos.Mutable pos, World world, float maxDistance) { return Math.min(maxDistance, LOCAL_ALTITUDE_FIELD.getValue(world, pos)) / maxDistance; } From 5a900e8601c29659ae5c20f40c1f42b1073ad1a0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 2 Oct 2024 23:32:27 +0100 Subject: [PATCH 056/110] Remove unneccessary injection --- .../unicopia/client/BatEyesApplicator.java | 16 +++++++++++----- .../unicopia/client/UnicopiaClient.java | 7 ------- .../unicopia/mixin/client/MixinGameRenderer.java | 14 +------------- 3 files changed, 12 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/BatEyesApplicator.java b/src/main/java/com/minelittlepony/unicopia/client/BatEyesApplicator.java index a3191d17..f9f26c79 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/BatEyesApplicator.java +++ b/src/main/java/com/minelittlepony/unicopia/client/BatEyesApplicator.java @@ -3,9 +3,9 @@ package com.minelittlepony.unicopia.client; import com.minelittlepony.unicopia.EquinePredicates; import net.minecraft.client.MinecraftClient; +import net.minecraft.entity.LivingEntity; import net.minecraft.entity.effect.StatusEffectInstance; import net.minecraft.entity.effect.StatusEffects; -import net.minecraft.entity.player.PlayerEntity; public class BatEyesApplicator { @@ -15,11 +15,17 @@ public class BatEyesApplicator { private final MinecraftClient client = MinecraftClient.getInstance(); + public float getWorldBrightness(float initial, LivingEntity entity, float tickDelta) { + if (!EquinePredicates.PLAYER_BAT.test(entity)) { + return initial; + } + return 0.6F; + } + public void enable() { - if (client.world != null) { - PlayerEntity player = client.player; - if (!player.hasStatusEffect(StatusEffects.NIGHT_VISION) && EquinePredicates.PLAYER_BAT.test(player)) { - player.addStatusEffect(new StatusEffectInstance(StatusEffects.NIGHT_VISION, 1, 1, false, false)); + if (client.world != null && client.player != null) { + if (!client.player.hasStatusEffect(StatusEffects.NIGHT_VISION) && EquinePredicates.PLAYER_BAT.test(client.player)) { + client.player.addStatusEffect(new StatusEffectInstance(StatusEffects.NIGHT_VISION, -1, 1, false, false)); batEyesApplied = true; } } diff --git a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java index 4e2a8ac4..8fb1e403 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java +++ b/src/main/java/com/minelittlepony/unicopia/client/UnicopiaClient.java @@ -53,9 +53,6 @@ public class UnicopiaClient implements ClientModInitializer { return Pony.of(MinecraftClient.getInstance().player); } - private final Lerp rainGradient = new Lerp(0); - private final Lerp thunderGradient = new Lerp(0); - public final Lerp tangentalSkyAngle = new Lerp(0, true); public final Lerp skyAngle = new Lerp(0, true); @@ -103,10 +100,6 @@ public class UnicopiaClient implements ClientModInitializer { return Unicopia.getConfig().preferredRace.get(); } - public static float getWorldBrightness(float initial) { - return 0.6F; - } - public UnicopiaClient() { instance = this; } diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinGameRenderer.java b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinGameRenderer.java index 2fe4abe2..d9effcf6 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinGameRenderer.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/client/MixinGameRenderer.java @@ -6,7 +6,6 @@ import org.spongepowered.asm.mixin.injection.At.Shift; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; -import com.minelittlepony.unicopia.EquinePredicates; import com.minelittlepony.unicopia.client.BatEyesApplicator; import com.minelittlepony.unicopia.client.UnicopiaClient; import com.minelittlepony.unicopia.client.render.shader.ViewportShader; @@ -17,7 +16,6 @@ import net.minecraft.client.render.GameRenderer; import net.minecraft.client.util.math.MatrixStack; import net.minecraft.util.math.RotationAxis; import net.minecraft.entity.LivingEntity; -import net.minecraft.entity.effect.StatusEffects; import net.minecraft.resource.SynchronousResourceReloader; @Mixin(value = GameRenderer.class, priority = Integer.MAX_VALUE) @@ -46,21 +44,11 @@ abstract class MixinGameRenderer implements AutoCloseable, SynchronousResourceRe BatEyesApplicator.INSTANCE.disable(); } - @Inject(method = "getNightVisionStrength(Lnet/minecraft/entity/LivingEntity;F)F", - at = @At("HEAD"), - cancellable = true) - private static void onGetNightVisionStrengthHead(LivingEntity entity, float tickDelta, CallbackInfoReturnable info) { - if (!entity.hasStatusEffect(StatusEffects.NIGHT_VISION)) { - info.setReturnValue(UnicopiaClient.getWorldBrightness(0)); - } - } @Inject(method = "getNightVisionStrength(Lnet/minecraft/entity/LivingEntity;F)F", at = @At("RETURN"), cancellable = true) private static void onGetNightVisionStrengthReturn(LivingEntity entity, float tickDelta, CallbackInfoReturnable info) { - if (entity.hasStatusEffect(StatusEffects.NIGHT_VISION) && EquinePredicates.PLAYER_BAT.test(entity)) { - info.setReturnValue(UnicopiaClient.getWorldBrightness(info.getReturnValueF())); - } + info.setReturnValue(BatEyesApplicator.INSTANCE.getWorldBrightness(info.getReturnValueF(), entity, tickDelta)); } @Inject(method = "render", From 2ad3f48f15236c08c20145e2813c605909859165 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 6 Oct 2024 18:26:44 +0100 Subject: [PATCH 057/110] Fixed muffins and rocks appearing invisible when thrown --- .../unicopia/item/HeavyProjectileItem.java | 5 +++-- .../PhysicsBodyProjectileEntity.java | 20 ++++++++++--------- .../unicopia/projectile/Projectile.java | 10 +++++----- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/item/HeavyProjectileItem.java b/src/main/java/com/minelittlepony/unicopia/item/HeavyProjectileItem.java index 16797e43..e76a2920 100644 --- a/src/main/java/com/minelittlepony/unicopia/item/HeavyProjectileItem.java +++ b/src/main/java/com/minelittlepony/unicopia/item/HeavyProjectileItem.java @@ -18,12 +18,13 @@ public class HeavyProjectileItem extends ProjectileItem { @Override public 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) { projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1); } projectile.pickupType = PersistentProjectileEntity.PickupPermission.ALLOWED; - projectile.setStack(stack.copy().split(1)); return projectile; } diff --git a/src/main/java/com/minelittlepony/unicopia/projectile/PhysicsBodyProjectileEntity.java b/src/main/java/com/minelittlepony/unicopia/projectile/PhysicsBodyProjectileEntity.java index 19b3c2bc..a831c804 100644 --- a/src/main/java/com/minelittlepony/unicopia/projectile/PhysicsBodyProjectileEntity.java +++ b/src/main/java/com/minelittlepony/unicopia/projectile/PhysicsBodyProjectileEntity.java @@ -55,16 +55,18 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl private RegistryKey damageType = UDamageTypes.ROCK; + public PhysicsBodyProjectileEntity(World world, ItemStack stack) { + super(UEntities.MUFFIN, world); + setStack(stack); + } + public PhysicsBodyProjectileEntity(EntityType type, World world) { super(type, world); } - public PhysicsBodyProjectileEntity(World world) { - this(UEntities.MUFFIN, world); - } - - public PhysicsBodyProjectileEntity(World world, @Nullable LivingEntity thrower) { + public PhysicsBodyProjectileEntity(World world, @Nullable LivingEntity thrower, ItemStack stack) { super(UEntities.MUFFIN, thrower, world); + setStack(stack); } @Override @@ -75,7 +77,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl } public void setStack(ItemStack stack) { - getDataTracker().set(ITEM, stack); + getDataTracker().set(ITEM, stack.copy()); } @Override @@ -89,7 +91,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl @Override protected ItemStack asItemStack() { - return getStack(); + return getStack().copy(); } public void setBouncy() { @@ -273,7 +275,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl super.writeCustomDataToNbt(nbt); ItemStack stack = getStack(); if (!stack.isEmpty()) { - nbt.put("Item", stack.writeNbt(new NbtCompound())); + nbt.put("item", stack.writeNbt(new NbtCompound())); } nbt.putString("damageType", damageType.getValue().toString()); } @@ -281,7 +283,7 @@ public class PhysicsBodyProjectileEntity extends PersistentProjectileEntity impl @Override public void readCustomDataFromNbt(NbtCompound nbt) { super.readCustomDataFromNbt(nbt); - setStack(ItemStack.fromNbt(nbt.getCompound("Item"))); + setStack(ItemStack.fromNbt(nbt.getCompound("item"))); if (nbt.contains("damageType", NbtElement.STRING_TYPE)) { Optional.ofNullable(Identifier.tryParse(nbt.getString("damageType"))).ifPresent(id -> { setDamageType(RegistryKey.of(RegistryKeys.DAMAGE_TYPE, id)); diff --git a/src/main/java/com/minelittlepony/unicopia/projectile/Projectile.java b/src/main/java/com/minelittlepony/unicopia/projectile/Projectile.java index c8b0c2a2..34f831ea 100644 --- a/src/main/java/com/minelittlepony/unicopia/projectile/Projectile.java +++ b/src/main/java/com/minelittlepony/unicopia/projectile/Projectile.java @@ -38,12 +38,12 @@ public interface Projectile extends ItemConvertible { default TypedActionResult triggerThrow(World world, PlayerEntity player, Hand hand) { ItemStack stack = player.getStackInHand(hand); - SoundEmitter.playSoundAt(player, - getThrowSound(stack), SoundCategory.NEUTRAL, - 0.5F, - 0.4F / (world.random.nextFloat() * 0.4F + 0.8F)); - if (!world.isClient) { + SoundEmitter.playSoundAt(player, + getThrowSound(stack), SoundCategory.NEUTRAL, + 0.5F, + 0.4F / (world.random.nextFloat() * 0.4F + 0.8F)); + world.spawnEntity(createProjectile(stack.copyWithCount(1), world, player)); } From 04a050658279d4ef489bc58662bca853d132cb94 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 15:01:58 +0100 Subject: [PATCH 058/110] Clean up soggy cloud textures slightly --- .../textures/block/soggy_cloud_side.png | Bin 7821 -> 9889 bytes .../textures/block/soggy_cloud_slab_side.png | Bin 7816 -> 9860 bytes .../textures/block/soggy_cloud_top.png | Bin 7270 -> 9420 bytes 3 files changed, 0 insertions(+), 0 deletions(-) diff --git a/src/main/resources/assets/unicopia/textures/block/soggy_cloud_side.png b/src/main/resources/assets/unicopia/textures/block/soggy_cloud_side.png index b030c4a7dceca964613f8faa473ecf333c4ff831..bfe6574f9d11dee7226150961281ca2c0895610b 100644 GIT binary patch delta 2674 zcmb7Fdr(tn7XNPEfgnkU5Lg}w1c{7s@*)o`7Dz4+#T`RXsk2Ub1Vne#K|xlna}lFL z1S6to)}_<+0o|@zT||woZfB*XONFj0YJJcZwY4HT%APMFt<(Oqy_s`!?)lF5 zJHOvK-6@T`OkMjtc7bhMPX&#?K=xe+KE{^9n{nhk!#9x$_ znFf_`b+}EBA`{}USZo%P!)CL&T#g@46u|TM=YeBYqV+%LU6fUoK*kRoS4*OXJ=;*K9p$+Hdb-{fx`z zmaoWtV`ZVOsCaeBnzftC$~Ra1VawK?_FcR8RM$8foQ(&X4mP*E<9e^NtNTxf|J-xD zx9`Khe)P8!CkM`*zu><3$)}e-r@k2a@?XPWT^$*_ar4$Ux9{A&H~#3m?;rp0Wb*0M zGpr0N^<7?VKT{?EWi$qZ&R}C@1g!!~7ciJo6-$_6Vds|yMXPskM5*;1$IfzNG}#Yl z7i=8#3zlieVjqQwsn9Tww*OCB)vwa#llG&spM;Gd9-V;s(J29X9ZinNUCm69B^jGP zDOyUikRl>LWXWMXwvZV($|XhFM2X9hC$f+zb|#I0RIqI1a>&8vRsznB8d7BCKa;yU zX%2b2&lq?WKoPb+fWR==D2#;*VB-&xqW)u~D94l9_(~e2svsl7R%RiULICChmt=@4 zL!lh;*vm4D1psJV?%MA|^ojA*#kIlu<=(B{`Xnh@Ubz@nz2IxY5tKi4?XjsQfDRJ4vt5*084Cg$U7N1zzWLb z;Ax6*J+szA=GK(B9F-U`)k4meQ4O%@Ho+kAs1bByDHg%OTo=JKov>`zfix9tLk@tA z#@axFoVFGm0ICE+R`G~;^w~0ComB|QsdydBo6wHV2}q9?_S8 zXARDQ#`MT>4uo?Wa-n4Hx|#ij(1XtCc%U^f)4gUlbQnRy_U{>_p!>^!ZfFwJt&sy1 zMv>qMP)*+3XCbBV?pei{d<3+%0QTD9yk-lS@MME^JTxmVULR8eEt7$;Ox$-SfDnza z4oZ@Rxa6f75%^T%H^IHoK>;^EFSm9K&1nFVQb1Mjfu|afgWvF_bRRQ3kXo3-emiz> z6dP#uyu6;K!MPH-MNoGMo(CqNz)Z_P$t+B12)f)heRXv5UkW#80=-tDwdu5qe4W;)(Bv1ZHQIceu_z(mIULXxs8<^_MvX?3VAN_7bQ& zp)?jkM6K1SlzQj-Ad;_DsFVt&;YZxwb3yAl!JI>v*26b}Rj@eSjMm^^BzF(rnI0ZV z-Sy)H1jaO8fAIi5b~iK4DLIDAOBz!4MHqResG|2@{@3|DYJ*U6nxp*V{88a*%irru zib92?CFekhq@Tt+`QS#|FzOdeU*B-$RImVzf7fjZb=&pgQp(UoTQ!auBqy|aY(qe^8KUs$IHIBFQft^?CTtH5A>`3ZCB2WZSBylJGCxRNeQ~9 z7BHT?x3{h)><(X7S87k|TSYyKQgU0Z)>J`m-n}=tt%3T3AFQaZoj9{L)YNL-bmWI^ z4?Z{Cymrcctz5eMTF*a?s^|3frb*t@EgPuIcWY;@JgsqG{Oq&efBbU6^P?5p+2+YW zF{O#w^)&a|@`~wgPozh(+U030+OoH}58ZE4b+n&6dRn8dtKn3cPQEa7i+LpV1H7ry zb05!1wO1MEw6wU5g~xMijSqF@<6pN;?whzx4GkVxk!HTXE$Z^y?2$u>wc>@}K78kh zIIQJJ`p%IHGD%{I{>9Y~_?ozHH>oxa+@9BDN;#3%8ZA;**V;DgSFNhv$Gf#!k=Ir( zk!T*3#*-D)i84;d!WWA>HZHK+vMPFqi*Fg$FE07V@LR9d8OoPdcbuKBY%7@B+_l9C QM}mto$={m)lA2fbKRG;mvH$=8 delta 756 zcmVr#t8K zvoi=u3IPPOeG-ZSBsMfRWHB>2IW0FhIWsLZHDh8eI59Y3EihqYGiG6CI5=WvF_SA5 zr4KeaH#aggH83Gc&@3V*iP?r~t$}lFpF9T?sU$Q{8VfWH;l|nBpTxe)a|;j?c^1%NlZ|QqFM<8!V&iXrzSO@zX#4pfLL=I)JkWU%&n!q!4ibvM0!wgy%#pwC z@2}tS>)&b>#6K^)l~@Pii(dEry)TyEsJEZ!^`!@5Jobt?Cm%koAFGINqkVtxFW05d zc?RFUzVP|?kALOJyzYzhJlShA$K>_ipK|zHo;fLm;NG{@-GA)0$s-deiqX}(RGu+s zyJbu$s4i@;j7(!9f?$(wKg1M+0qu4u#=6&5Xw8^~aE?S4wuup7m>MD+y6$UdWOlWU z2_j-f)T-rhU+e0F0}s>m^6h`gL;*189I_x_9upx#!5ov!Oyis}xw#p0;ALvpzTU1C z-OaA8Bae)TTG!f^9|qd&+Kd?9_vV~u42{h5$)Hv-35X8bO~1V(os;|RX6A&&zPTL= z$~9^ip@2bTB(uBe>Oyp6AV0Q%weJl9nTfYkDZ2X?r9%ky?ym}!+aW9@W4fDlFGh~- mwuHt!=fgB&*G3_R2LAyJ)_Jsvi9$1~x1*8>Y z+Yy2X{vjBFTBa8Q(!-gerC4=r#d_i&UiD(et7@rIrSD5f>-d+<@a??K+xOo0d++zX zH~DJbs-C?yij>~1jb2CWuWeEZMuc=)9hb;z6Sc;078FAw%OV;*M-(Cuatb0`I{qMD z&`CmsL=d9_y9jg~FTwJH?l-FAID&NH#6ckG)CGik@eWur=QDDC1mx~LgDx$;^sf?C;KtPu_g0m8llt?V5DDbWaKcbXk!6$-ElK7e}(#SGKS6RD9 z7M0w7$S=G9zDi%XqKcOLPYehQik=jsj*a8u4GBh5VoEBXHX}VFb8b#<-n{(z3yO-Z zC5ua!EM2*3b@`eP)~?%F{ozNOYBt;I?DgBW@7UR}%dxk)rS-FYpSSJr=_F*D56ysC5~VvK1pV&rOY={S1DtXYxlGtqNDWL_x%c2^vnHK+?D7D z69a_6ASbt1qgFL0Zf4miqXL&Hg?vr}Ho6^=a2S;uU<05+6HbW_kW7RoK)v`hu^&I)}E&kg2%>ZwJLmTZt)dx2c<{9H zPb5@+Mbf$4e~ePpCtG{7X|cZ&4X!w~Pf>I@MRL;6ctvUqb9DVszHmrByKibh)yYMj z-E^C+E3?#ho`t@>vh`y0fncF}neE-7y%)&9`iTeUoNis#JzIKXOV+NhBfjZ=!!T*- z7yNmyPZ`u-{_Mzd9sOnQ++<~b!IH-6vlmYsKO1`P${0us9rmve#TR4-KPUC8p=5&)x+XZkFco z;9?SdzByH>i%G@8#KI)m*uq>lH90v|*TldiP1nLG$xPS8+&I-d*~rw$&@y?lu;@}v zGfQ)GBNJ0|LnC7g3sVavE(HYzcTe8{tFY9f;>`R!TO}hsLjyfylgST71Nosghd^zf z>?kIWF19&etdVu|WtjvHvBp}D&kPIHHwnGj(Uo zw5`+F6%H`*ysG_p!HD4)$Ils#<$6kt8q>;|be;7I#F;r}>qjgwO+2ATEKO55QyA1_DQ>pPH2YZnk|(oNm>x5TJT(3FAn8kyMdowQ*-%-@Vf!GJ=n#UD6?}eZDF0Z!1h{9 z{n^i7d)EIKiJD-iXB@K8Y?AfH{=&X<@1$RU>svSdL`Th@?HWrzeAu%8ZMR6G$#JJY zmv_(0_MQ``Z}Y$IPjvCx+LEa3GqpiQ53QaBpS8Oh#?7rLQ5<1!`{U(7nScDo>x-wH T{pp|q3`_=3S3j3^P6M%D@ z6p4=o;##b3H$+rqTrHxtwz{RhOYO9@SSlTd`lw~;Y}G=I?%1;DyAZe2{bzeKH*@ay zo$ve}=Y-1*_JXxNl@Nt>q^-dZb@)^qi(!nGG34sBxmq?^2Z15iV8m$bCyc^y4C8MM zpN-K2{QGjxTM5{xcK;F)g$T2Df3g~ z5l<`W2VK}&d%{4QK$wi11iKk$M z94F=Y%xNqMhzfB2n$?1&l9WIgBBI3-NH`+Hz$=oVNP&Q&V7C$WF-k7rB9yvC!bqDV zBxR+7Y3k?}r55(TA5}hlOQo-VshJi>KNJ%imo_h5osntC$~Lk&xkV;(af!uRy0l_h z<>OUPJn5`))z&Rv@$9Plm;co8%IY<*wyayD~I5ZLf80f8D>UXZN1Hz5DtO z4IDo5*3q|*y>s%^=`&}~o&R9yQ|_~oi=U5vacS(z)oa(kzVXe(KPPX0KQ;Zsoxt6D z|3=D?(%?0#?H9`App2j>k_th}aH0W8ms0|zP8hMs7UEbLnZh)Q6onn#{qNJM`tn;* z)h`W;qg940X}2GW;bP->ZU3LN=3k{PDD8o={|Xz!q$CdgBRM&?5DUDn_PbSnPsS#f z!d4J5Y*w_Cm=#N?dYf6BWLA{p%l#gItIe!vdl)TmwV9J4SQ-NXf%b_L3fp3O!tW72 zj*2{~_HR!aHb-G)D7ylRq`@)<=iSX7bstd*Xndi=HZwh0jqyAU#UNgNH={aP}duF_ahP=YZ=ZaFoLs*=U>!47C6=rB|V)&`q1Y_YVngAMTYKUM#$k%OzgQy1-l;S(XPdzlG>m*__ z0t7%_Igtx1=YT~EXGX&`4R$N$epNUm@!mfeX2D$l&)T4$+n^4bO}?MO7QwhjRnLbn z5-|s_`G#Rb&=K&i4{1VN%aKc{c4ZZ)_ca4A&JBF{?x3H{dLW^NUx^wqN)B2z*ch}O zl=Xwea>OwiTHAysOH>L08Ypn0hXg3(qfa#9_Y|SO67n>38lIf#DA@&x-B5=@9WI#> zUcw5F-R1hnEn-5Z9LSJ(2$fTBtaUnSoEmKwW7HT7+8m9;WrQfp>2T^?&KzU5!#f(f zJKV^y`W!vO8nd$4ETi7LF)S8my}QF~vbpzpMeu#@6^1AN&*Fd~e3bC28N#T46Mq!B_ai4EI8* zIHGaMNA=^&&r0Gq9{6^w?yvPnC-+ak_{QaBt}P=yw^Z@1)>E>+(}A^9tKMk5-tk_3 zXG8pFk=&ya#etjGiq25E_9E-kqo=m(FK>R%dd_j7`GVokteas;;Jw z>u$gDVfN&A9~>Y5(exZm$$rXv-jJVMQb=F=IRDTmfxLljZp#K$i`}GPJo94*+rz4? z{?*M_7I|t5BUCn5vus}5fp5F(x)N)Y?V78_C-i}--l6*NZ*tpB4XF=LrIh)k)~?t) zQNmp(^4?M|m{wJ#tS%!h+=flH&-@`UMWt-id5_&}wOV}l54Pa~`ts;z6SY6L{mT8F zcN)KZOd|Q=`2H2=k7rn_12(WRPZ zmgZ(=X2zz576z84mWE1P3JMDDp1uKAVW~yMnfZCPN=ABy271OOlNrSV?VvV?z--nw zFtjo-0BfqqEwJ*t~c6VWr zWzc7^nxbc*Jo$iWz{AyI4YV><#_7#J9rdb&7oZTm@&C_CU|G;O;oBHgF zu_vzjG|T@q{Nj0hk}As%jZ>*F-`zjJEpdRU<-Nv%Ms9}^~d>%}lId3+b)2`q97w?<qN(-ciYol?#^8PLo8_Z_I<|;LTmiIqY8=zQ#m^Rq|WKu$GYbBvGvzaG#=Ao%Jv7$k^nx&~1%iZ&+wz znv_@IyWp>e>g#uN&o}$Qa-`iwH}qh;zh^_@XUqOiTlUEp|5zBxP#ncL|GoY#$sNy} gelV;OTJ?ax?&{Yf{eMqgfsxAK>FVdQ&MBb@0P|KK0ssI2 From add128cbee22fb00d256412094af54d489bd5b87 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 15:02:26 +0100 Subject: [PATCH 059/110] Use the bucket tag for filling jars instead of just the vanilla bucket --- .../unicopia/block/jar/FluidOnlyJarContents.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java b/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java index 0cdcab4b..49f0e62f 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java +++ b/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java @@ -5,11 +5,11 @@ import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents; import com.minelittlepony.unicopia.block.ItemJarBlock.TileData; import com.minelittlepony.unicopia.util.FluidHelper; +import net.fabricmc.fabric.api.tag.convention.v2.ConventionalItemTags; import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants; import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; -import net.minecraft.item.Items; import net.minecraft.nbt.NbtCompound; import net.minecraft.util.Hand; import net.minecraft.util.TypedActionResult; @@ -27,7 +27,7 @@ public record FluidOnlyJarContents ( @Override public TypedActionResult interact(PlayerEntity player, Hand hand) { ItemStack stack = player.getStackInHand(hand); - if (stack.isOf(Items.BUCKET)) { + if (stack.isIn(ConventionalItemTags.EMPTY_BUCKETS)) { long remainder = FluidHelper.deposit(stack, player, hand, fluid, amount); tile.markDirty(); fluid.getFluid().getBucketFillSound().ifPresent(sound -> player.playSound(sound, 1, 1)); From c89f7209e95a89de234770acfd01d22eccaa9a9c Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 15:10:06 +0100 Subject: [PATCH 060/110] Fixed not being able to collect water from soggy cloud stairs --- .../unicopia/block/cloud/SoggyCloudStairsBlock.java | 11 +++++++++++ .../unicopia/block/jar/FluidOnlyJarContents.java | 2 +- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/SoggyCloudStairsBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/SoggyCloudStairsBlock.java index 9e51e398..2efff68b 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/SoggyCloudStairsBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/SoggyCloudStairsBlock.java @@ -8,10 +8,15 @@ import com.minelittlepony.unicopia.block.state.StateUtil; import net.minecraft.block.Block; import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; import net.minecraft.state.StateManager; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.world.BlockView; +import net.minecraft.world.World; public class SoggyCloudStairsBlock extends CloudStairsBlock implements Soakable { @@ -34,6 +39,12 @@ public class SoggyCloudStairsBlock extends CloudStairsBlock implements Soakable return dryBlock.get().getPickStack(world, pos, state); } + @Deprecated + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + return Soakable.tryCollectMoisture(state, world, pos, player, hand, hit); + } + @Nullable @Override public BlockState getStateWithMoisture(BlockState state, int moisture) { diff --git a/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java b/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java index 49f0e62f..b3ac0222 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java +++ b/src/main/java/com/minelittlepony/unicopia/block/jar/FluidOnlyJarContents.java @@ -5,7 +5,7 @@ import com.minelittlepony.unicopia.block.ItemJarBlock.JarContents; import com.minelittlepony.unicopia.block.ItemJarBlock.TileData; import com.minelittlepony.unicopia.util.FluidHelper; -import net.fabricmc.fabric.api.tag.convention.v2.ConventionalItemTags; +import net.fabricmc.fabric.api.tag.convention.v1.ConventionalItemTags; import net.fabricmc.fabric.api.transfer.v1.fluid.FluidConstants; import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant; import net.minecraft.entity.player.PlayerEntity; From c877016ac78732ab7d29b1d0207482d288df5343 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 15:17:24 +0100 Subject: [PATCH 061/110] You can now soak clouds using bottles of water --- .../block/cloud/NaturalCloudBlock.java | 3 +- .../block/cloud/PoreousCloudBlock.java | 11 +++++++ .../block/cloud/PoreousCloudStairsBlock.java | 12 +++++++ .../unicopia/block/cloud/Soakable.java | 32 +++++++++++++------ 4 files changed, 48 insertions(+), 10 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java index 27a569d9..e950ba4b 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java @@ -29,6 +29,7 @@ public class NaturalCloudBlock extends PoreousCloudBlock { this.compactedBlock = compactedBlock; } + @Deprecated @Override public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { ItemStack stack = player.getStackInHand(hand); @@ -41,6 +42,6 @@ public class NaturalCloudBlock extends PoreousCloudBlock { return ActionResult.SUCCESS; } - return ActionResult.PASS; + return super.onUse(state, world, pos, player, hand, hit); } } diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudBlock.java index 15303184..171b8a9e 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudBlock.java @@ -7,9 +7,14 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.block.state.StateUtil; import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; import net.minecraft.server.world.ServerWorld; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.random.Random; +import net.minecraft.world.World; public class PoreousCloudBlock extends CloudBlock implements Soakable { @Nullable @@ -20,6 +25,12 @@ public class PoreousCloudBlock extends CloudBlock implements Soakable { this.soggyBlock = soggyBlock; } + @Deprecated + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + return Soakable.tryDepositMoisture(state, world, pos, player, hand, hit); + } + @Nullable @Override public BlockState getStateWithMoisture(BlockState state, int moisture) { diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudStairsBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudStairsBlock.java index 3ee498a1..2a8e4f81 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudStairsBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/PoreousCloudStairsBlock.java @@ -7,6 +7,12 @@ import org.jetbrains.annotations.Nullable; import com.minelittlepony.unicopia.block.state.StateUtil; import net.minecraft.block.BlockState; +import net.minecraft.entity.player.PlayerEntity; +import net.minecraft.util.ActionResult; +import net.minecraft.util.Hand; +import net.minecraft.util.hit.BlockHitResult; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; public class PoreousCloudStairsBlock extends CloudStairsBlock implements Soakable { @@ -17,6 +23,12 @@ public class PoreousCloudStairsBlock extends CloudStairsBlock implements Soakabl this.soggyBlock = soggyBlock; } + @Deprecated + @Override + public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + return Soakable.tryDepositMoisture(state, world, pos, player, hand, hit); + } + @Nullable @Override public BlockState getStateWithMoisture(BlockState state, int moisture) { diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java index d192c71d..44d6a95e 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/Soakable.java @@ -9,8 +9,11 @@ import com.minelittlepony.unicopia.USounds; import net.minecraft.block.BlockState; import net.minecraft.entity.player.PlayerEntity; import net.minecraft.item.ItemStack; +import net.minecraft.item.ItemUsage; import net.minecraft.item.Items; import net.minecraft.particle.ParticleTypes; +import net.minecraft.potion.PotionUtil; +import net.minecraft.potion.Potions; import net.minecraft.server.world.ServerWorld; import net.minecraft.sound.SoundCategory; import net.minecraft.sound.SoundEvents; @@ -50,15 +53,8 @@ public interface Soakable { static ActionResult tryCollectMoisture(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { if (state.getBlock() instanceof Soakable soakable) { ItemStack stack = player.getStackInHand(hand); - if (stack.getItem() == Items.GLASS_BOTTLE) { - if (!player.isCreative()) { - stack.split(1); - } - if (stack.isEmpty()) { - player.setStackInHand(hand, Items.POTION.getDefaultStack()); - } else { - player.giveItemStack(Items.POTION.getDefaultStack()); - } + if (stack.isOf(Items.GLASS_BOTTLE)) { + player.setStackInHand(hand, ItemUsage.exchangeStack(stack, player, Items.POTION.getDefaultStack(), false)); world.playSound(player, player.getX(), player.getY(), player.getZ(), USounds.Vanilla.ITEM_BOTTLE_FILL, SoundCategory.NEUTRAL, 1, 1); world.emitGameEvent(player, GameEvent.FLUID_PICKUP, pos); updateMoisture(soakable, state, world, pos, soakable.getMoisture(state) - 1); @@ -67,6 +63,24 @@ public interface Soakable { } } + return tryDepositMoisture(state, world, pos, player, hand, hit); + } + + static ActionResult tryDepositMoisture(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) { + if (state.getBlock() instanceof Soakable soakable) { + ItemStack stack = player.getStackInHand(hand); + if (soakable.getMoisture(state) < 7 + && stack.isOf(Items.POTION) + && PotionUtil.getPotion(stack) == Potions.WATER) { + player.setStackInHand(hand, ItemUsage.exchangeStack(stack, player, Items.GLASS_BOTTLE.getDefaultStack(), false)); + world.playSound(player, player.getX(), player.getY(), player.getZ(), USounds.Vanilla.ITEM_BUCKET_EMPTY, SoundCategory.NEUTRAL, 1, 1); + world.emitGameEvent(player, GameEvent.FLUID_PLACE, pos); + updateMoisture(soakable, state, world, pos, soakable.getMoisture(state) + 1); + + return ActionResult.SUCCESS; + } + } + return ActionResult.PASS; } From b61ef575fb1cf27c733afa13a09e46277bd01065 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 16:25:11 +0100 Subject: [PATCH 062/110] Fix incorrect translation --- src/main/resources/assets/unicopia/lang/en_us.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index 6005597f..df90e36b 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -799,7 +799,7 @@ "gui.unicopia.tribe_selection.options": "Available Tribes:", "gui.unicopia.tribe_selection.options.disabled": "Option Unavailable", - "gui.unicopia.tribe_selection.describe.unicopia.human": "Got it alone", + "gui.unicopia.tribe_selection.describe.unicopia.human": "Go it alone", "gui.unicopia.tribe_selection.describe.unicopia.earth": "Join the Earth Tribe", "gui.unicopia.tribe_selection.describe.unicopia.unicorn": "Join the Unicorn Tribe, master the arcane arts", "gui.unicopia.tribe_selection.describe.unicopia.pegasus": "Join the Pegasus Tribe, soar with the Wonderbolts", From 7302bd5632557e1ed02ca988684c4bf75c4d442a Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 23:07:50 +0100 Subject: [PATCH 063/110] Fixed snow gathering on clouds / clouds blocking snow from gathering below them --- .../java/com/minelittlepony/unicopia/block/UBlocks.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java index 521281ac..70de855b 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java +++ b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java @@ -197,7 +197,7 @@ public interface UBlocks { Block SLIME_PUSTULE = register("slime_pustule", new SlimePustuleBlock(Settings.copy(Blocks.SLIME_BLOCK)), ItemGroups.NATURAL); Block SHAPING_BENCH = register("shaping_bench", new ShapingBenchBlock(Settings.create().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL)), ItemGroups.FUNCTIONAL); - Block CLOUD = register("cloud", new NaturalCloudBlock(Settings.create().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL), true, + Block CLOUD = register("cloud", new NaturalCloudBlock(Settings.create().notSolid().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL), true, () -> UBlocks.SOGGY_CLOUD, () -> UBlocks.COMPACTED_CLOUD), ItemGroups.NATURAL); Block COMPACTED_CLOUD = register("compacted_cloud", new CompactedCloudBlock(CLOUD.getDefaultState())); @@ -216,14 +216,14 @@ public interface UBlocks { () -> UBlocks.COMPACTED_CLOUD_BRICKS), ItemGroups.BUILDING_BLOCKS); Block COMPACTED_CLOUD_BRICKS = register("compacted_cloud_bricks", new CompactedCloudBlock(CLOUD_BRICKS.getDefaultState())); Block CLOUD_BRICK_SLAB = register("cloud_brick_slab", new CloudSlabBlock(Settings.copy(CLOUD_BRICKS), false, null), ItemGroups.BUILDING_BLOCKS); - Block CLOUD_BRICK_STAIRS = register("cloud_brick_stairs", new CloudStairsBlock(CLOUD_BRICKS.getDefaultState(), Settings.copy(CLOUD_PLANKS)), ItemGroups.BUILDING_BLOCKS); + Block CLOUD_BRICK_STAIRS = register("cloud_brick_stairs", new CloudStairsBlock(CLOUD_BRICKS.getDefaultState(), Settings.copy(CLOUD_BRICKS)), ItemGroups.BUILDING_BLOCKS); Block ETCHED_CLOUD = register("etched_cloud", new NaturalCloudBlock(Settings.copy(CLOUD_BRICKS), false, null, () -> UBlocks.COMPACTED_CLOUD_BRICKS), ItemGroups.BUILDING_BLOCKS); Block COMPACTED_ETCHED_CLOUD = register("compacted_etched_cloud", new CompactedCloudBlock(ETCHED_CLOUD.getDefaultState())); Block ETCHED_CLOUD_SLAB = register("etched_cloud_slab", new CloudSlabBlock(Settings.copy(ETCHED_CLOUD), false, null), ItemGroups.BUILDING_BLOCKS); - Block ETCHED_CLOUD_STAIRS = register("etched_cloud_stairs", new CloudStairsBlock(ETCHED_CLOUD.getDefaultState(), Settings.copy(CLOUD_PLANKS)), ItemGroups.BUILDING_BLOCKS); + Block ETCHED_CLOUD_STAIRS = register("etched_cloud_stairs", new CloudStairsBlock(ETCHED_CLOUD.getDefaultState(), Settings.copy(ETCHED_CLOUD)), ItemGroups.BUILDING_BLOCKS); SoggyCloudBlock SOGGY_CLOUD = register("soggy_cloud", new SoggyCloudBlock(Settings.copy(CLOUD).hardness(0.7F), () -> UBlocks.CLOUD)); SoggyCloudSlabBlock SOGGY_CLOUD_SLAB = register("soggy_cloud_slab", new SoggyCloudSlabBlock(Settings.copy(SOGGY_CLOUD), () -> UBlocks.CLOUD_SLAB)); From adf81b9b51f2cfdcd91c8dcad163a9dc9e65d003 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 8 Oct 2024 23:07:50 +0100 Subject: [PATCH 064/110] Fixed snow gathering on clouds / clouds blocking snow from gathering below them --- .../java/com/minelittlepony/unicopia/block/UBlocks.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java index 521281ac..70de855b 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java +++ b/src/main/java/com/minelittlepony/unicopia/block/UBlocks.java @@ -197,7 +197,7 @@ public interface UBlocks { Block SLIME_PUSTULE = register("slime_pustule", new SlimePustuleBlock(Settings.copy(Blocks.SLIME_BLOCK)), ItemGroups.NATURAL); Block SHAPING_BENCH = register("shaping_bench", new ShapingBenchBlock(Settings.create().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL)), ItemGroups.FUNCTIONAL); - Block CLOUD = register("cloud", new NaturalCloudBlock(Settings.create().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL), true, + Block CLOUD = register("cloud", new NaturalCloudBlock(Settings.create().notSolid().mapColor(MapColor.OFF_WHITE).hardness(0.3F).resistance(0).sounds(BlockSoundGroup.WOOL), true, () -> UBlocks.SOGGY_CLOUD, () -> UBlocks.COMPACTED_CLOUD), ItemGroups.NATURAL); Block COMPACTED_CLOUD = register("compacted_cloud", new CompactedCloudBlock(CLOUD.getDefaultState())); @@ -216,14 +216,14 @@ public interface UBlocks { () -> UBlocks.COMPACTED_CLOUD_BRICKS), ItemGroups.BUILDING_BLOCKS); Block COMPACTED_CLOUD_BRICKS = register("compacted_cloud_bricks", new CompactedCloudBlock(CLOUD_BRICKS.getDefaultState())); Block CLOUD_BRICK_SLAB = register("cloud_brick_slab", new CloudSlabBlock(Settings.copy(CLOUD_BRICKS), false, null), ItemGroups.BUILDING_BLOCKS); - Block CLOUD_BRICK_STAIRS = register("cloud_brick_stairs", new CloudStairsBlock(CLOUD_BRICKS.getDefaultState(), Settings.copy(CLOUD_PLANKS)), ItemGroups.BUILDING_BLOCKS); + Block CLOUD_BRICK_STAIRS = register("cloud_brick_stairs", new CloudStairsBlock(CLOUD_BRICKS.getDefaultState(), Settings.copy(CLOUD_BRICKS)), ItemGroups.BUILDING_BLOCKS); Block ETCHED_CLOUD = register("etched_cloud", new NaturalCloudBlock(Settings.copy(CLOUD_BRICKS), false, null, () -> UBlocks.COMPACTED_CLOUD_BRICKS), ItemGroups.BUILDING_BLOCKS); Block COMPACTED_ETCHED_CLOUD = register("compacted_etched_cloud", new CompactedCloudBlock(ETCHED_CLOUD.getDefaultState())); Block ETCHED_CLOUD_SLAB = register("etched_cloud_slab", new CloudSlabBlock(Settings.copy(ETCHED_CLOUD), false, null), ItemGroups.BUILDING_BLOCKS); - Block ETCHED_CLOUD_STAIRS = register("etched_cloud_stairs", new CloudStairsBlock(ETCHED_CLOUD.getDefaultState(), Settings.copy(CLOUD_PLANKS)), ItemGroups.BUILDING_BLOCKS); + Block ETCHED_CLOUD_STAIRS = register("etched_cloud_stairs", new CloudStairsBlock(ETCHED_CLOUD.getDefaultState(), Settings.copy(ETCHED_CLOUD)), ItemGroups.BUILDING_BLOCKS); SoggyCloudBlock SOGGY_CLOUD = register("soggy_cloud", new SoggyCloudBlock(Settings.copy(CLOUD).hardness(0.7F), () -> UBlocks.CLOUD)); SoggyCloudSlabBlock SOGGY_CLOUD_SLAB = register("soggy_cloud_slab", new SoggyCloudSlabBlock(Settings.copy(SOGGY_CLOUD), () -> UBlocks.CLOUD_SLAB)); From 02b62372cf0f6fb5afee82fa934af9fe9ab2f90d Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 9 Oct 2024 00:00:58 +0100 Subject: [PATCH 065/110] Remove debug logging --- .../java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java index 6381eda2..6a4adb14 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -174,7 +174,6 @@ public class CloudBlock extends Block implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - System.out.println(InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds()); return type != NavigationType.LAND || !InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds(); } From 83048f2a6b087385728be96ca9b744aa98a6b881 Mon Sep 17 00:00:00 2001 From: Sollace Date: Wed, 9 Oct 2024 00:01:25 +0100 Subject: [PATCH 066/110] Remove debug logging --- .../java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java index 6381eda2..6a4adb14 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/CloudBlock.java @@ -174,7 +174,6 @@ public class CloudBlock extends Block implements CloudLike { @Override @Deprecated public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) { - System.out.println(InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds()); return type != NavigationType.LAND || !InteractionManager.getInstance().getPathingEquineContext().collidesWithClouds(); } From 49847d14794e26aaf7be199878308c6168ffbfd0 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 10 Oct 2024 17:29:28 +0100 Subject: [PATCH 067/110] Fix regressions --- .../unicopia/client/gui/DismissSpellScreen.java | 5 +++++ .../unicopia/client/gui/TribeConfirmationScreen.java | 7 +++++-- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java index cddf13b9..bd5833b3 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/DismissSpellScreen.java @@ -101,6 +101,11 @@ public class DismissSpellScreen extends GameGui { matrices.pop(); } + @Override + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { + + } + @Override public boolean shouldPause() { return false; diff --git a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java index d329b50b..41b08861 100644 --- a/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java +++ b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java @@ -103,7 +103,7 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud { } @Override - public void render(DrawContext context, int mouseX, int mouseY, float delta) { + public void renderBackground(DrawContext context, int mouseX, int mouseY, float delta) { context.getMatrices().push(); context.getMatrices().translate(0, 0, -2); if (parent != null) { @@ -112,6 +112,7 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud { parent.render(context, -1, -1, delta); context.getMatrices().pop(); } + renderInGameBackground(context); final int columnHeight = 180; final int columnWidth = 310; @@ -132,9 +133,11 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud { context.drawTexture(TribeSelectionScreen.TEXTURE, left + 35, top, 148, 70, 21, 50); textBody.render(context, mouseX, mouseY, delta); context.getMatrices().pop(); + context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 5, 10, 70, 69, 50); context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 15, 10, 70, 69, 50); - super.render(context, mouseX, mouseY, delta); + + } @Override From cab9b517c26a97396a9a7b02238338b582924724 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 10 Oct 2024 18:04:05 +0100 Subject: [PATCH 068/110] Fix sweet apple acres advancement --- .../datagen/providers/UAdvancementsProvider.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java index 5ab34f97..54553946 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java @@ -1,5 +1,6 @@ package com.minelittlepony.unicopia.datagen.providers; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; @@ -95,7 +96,7 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { parent.child(UItems.TOAST).criterion("has_toast", hasItems(UItems.TOAST)).build(consumer, "toast") .child(UItems.BURNED_TOAST).hidden().criterion("has_burned_toast", hasItems(UItems.BURNED_TOAST)).build(consumer, "burn_toast"); parent.child(UItems.GREEN_APPLE).criterion("has_apple", hasItems(UTags.Items.FRESH_APPLES)).build(consumer, "apple_route").children(p -> { - p.child(UItems.SWEET_APPLE).criterion("has_all_apples", hasItems(Items.APPLE, UItems.GREEN_APPLE, UItems.SWEET_APPLE, UItems.SOUR_APPLE, UItems.ROTTEN_APPLE, UItems.ZAP_APPLE, UItems.COOKED_ZAP_APPLE, Items.GOLDEN_APPLE)).build(consumer, "sweet_apple_acres"); + requireAllItems(p.child(UItems.SWEET_APPLE), Items.APPLE, UItems.GREEN_APPLE, UItems.SWEET_APPLE, UItems.SOUR_APPLE, UItems.ROTTEN_APPLE, UItems.ZAP_APPLE, UItems.COOKED_ZAP_APPLE, Items.GOLDEN_APPLE).build(consumer, "sweet_apple_acres"); p.child(UItems.ZAP_BULB).criterion("has_zap_apple", hasItems(UItems.ZAP_APPLE)).build(consumer, "trick_apple").children(pp -> { pp.child(UItems.ZAP_APPLE).hidden().criterion("eat_trick_apple", CustomEventCriterion.createFlying("eat_trick_apple")).build(consumer, "eat_trick_apple"); pp.child(UItems.ZAP_APPLE).hidden().criterion("feed_trick_apple", CustomEventCriterion.createFlying("feed_trick_apple")).build(consumer, "feed_trick_apple"); @@ -130,6 +131,13 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { .child(UItems.GOLDEN_FEATHER).apply(d -> applyShedFeatherCriterions(d, 2048, 10000)).frame(AdvancementFrame.GOAL).build(consumer, "dedicated_flier"); } + private AdvancementDisplayBuilder requireAllItems(AdvancementDisplayBuilder builder, ItemConvertible...items) { + List.of(items).forEach(item -> { + builder.criterion("has_" + Registries.ITEM.getId(item.asItem()).getPath(), hasItems(item)); + }); + return builder.criteriaMerger(AdvancementRequirements.CriterionMerger.AND); + } + private AdvancementDisplayBuilder applyShedFeatherCriterions(AdvancementDisplayBuilder builder, int repeats, int experience) { for (int i = 1; i <= repeats; i++) { builder.criterion("shed_feather_" + i, CustomEventCriterion.createFlying("shed_feather", i)); From 7ecf4b136790bab03eece3b1a67b2548b30129d6 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 10 Oct 2024 18:04:05 +0100 Subject: [PATCH 069/110] Fix sweet apple acres advancement --- .../datagen/providers/UAdvancementsProvider.java | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java index de390bfb..394516f9 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java @@ -1,5 +1,6 @@ package com.minelittlepony.unicopia.datagen.providers; +import java.util.List; import java.util.Optional; import java.util.Set; import java.util.function.Consumer; @@ -95,7 +96,7 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { parent.child(UItems.TOAST).criterion("has_toast", hasItems(UItems.TOAST)).build(consumer, "toast") .child(UItems.BURNED_TOAST).hidden().criterion("has_burned_toast", hasItems(UItems.BURNED_TOAST)).build(consumer, "burn_toast"); parent.child(UItems.GREEN_APPLE).criterion("has_apple", hasItems(UTags.Items.FRESH_APPLES)).build(consumer, "apple_route").children(p -> { - p.child(UItems.SWEET_APPLE).criterion("has_all_apples", hasItems(Items.APPLE, UItems.GREEN_APPLE, UItems.SWEET_APPLE, UItems.SOUR_APPLE, UItems.ROTTEN_APPLE, UItems.ZAP_APPLE, UItems.COOKED_ZAP_APPLE, Items.GOLDEN_APPLE)).build(consumer, "sweet_apple_acres"); + requireAllItems(p.child(UItems.SWEET_APPLE), Items.APPLE, UItems.GREEN_APPLE, UItems.SWEET_APPLE, UItems.SOUR_APPLE, UItems.ROTTEN_APPLE, UItems.ZAP_APPLE, UItems.COOKED_ZAP_APPLE, Items.GOLDEN_APPLE).build(consumer, "sweet_apple_acres"); p.child(UItems.ZAP_BULB).criterion("has_zap_apple", hasItems(UItems.ZAP_APPLE)).build(consumer, "trick_apple").children(pp -> { pp.child(UItems.ZAP_APPLE).hidden().criterion("eat_trick_apple", CustomEventCriterion.createFlying("eat_trick_apple")).build(consumer, "eat_trick_apple"); pp.child(UItems.ZAP_APPLE).hidden().criterion("feed_trick_apple", CustomEventCriterion.createFlying("feed_trick_apple")).build(consumer, "feed_trick_apple"); @@ -130,6 +131,13 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { .child(UItems.GOLDEN_FEATHER).apply(d -> applyShedFeatherCriterions(d, 2048, 10000)).frame(AdvancementFrame.GOAL).build(consumer, "dedicated_flier"); } + private AdvancementDisplayBuilder requireAllItems(AdvancementDisplayBuilder builder, ItemConvertible...items) { + List.of(items).forEach(item -> { + builder.criterion("has_" + Registries.ITEM.getId(item.asItem()).getPath(), hasItems(item)); + }); + return builder.criteriaMerger(CriterionMerger.AND); + } + private AdvancementDisplayBuilder applyShedFeatherCriterions(AdvancementDisplayBuilder builder, int repeats, int experience) { for (int i = 1; i <= repeats; i++) { builder.criterion("shed_feather_" + i, CustomEventCriterion.createFlying("shed_feather", i)); From f1ddb2381daabd180fb2181e982756b5f6d74d02 Mon Sep 17 00:00:00 2001 From: Sollace Date: Thu, 10 Oct 2024 19:03:48 +0100 Subject: [PATCH 070/110] Fixed the trick apple recipes # Conflicts: # src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/TrickCraftingRecipeJsonBuilder.java --- .../com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java b/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java index 127e1c42..cd7764b2 100644 --- a/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java +++ b/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java @@ -18,6 +18,11 @@ public class ZapAppleRecipe extends ShapelessRecipe { super(group, category, output, input); } + @Override + public RecipeSerializer getSerializer() { + return URecipes.ZAP_APPLE_SERIALIZER; + } + public static class Serializer implements RecipeSerializer { private static final Codec CODEC = RecordCodecBuilder.create(instance -> instance.group( Codec.STRING.optionalFieldOf("group", "").forGetter(ZapAppleRecipe::getGroup), From 001bf74afce52ba27cfe39c4291c11ecf24c9b0a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Thu, 10 Oct 2024 21:30:51 +0100 Subject: [PATCH 071/110] New translations en_us.json (French) --- src/main/resources/assets/unicopia/lang/fr_fr.json | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/main/resources/assets/unicopia/lang/fr_fr.json b/src/main/resources/assets/unicopia/lang/fr_fr.json index ce7fe820..c1cfc8ea 100644 --- a/src/main/resources/assets/unicopia/lang/fr_fr.json +++ b/src/main/resources/assets/unicopia/lang/fr_fr.json @@ -41,7 +41,7 @@ "tla.category.unicopia.spellbook": "Livre de sortilèges", "tla.category.unicopia.cloud_shaping": "Façonnage", "tla.category.unicopia.growing": "Croissance", - "tla.category.unicopia.altar": "Sombre Rituel", + "tla.category.unicopia.altar": "Rituel sombre", "recipe.unicopia.altar.instruction": "Placer l'objet dans les flammes", "recipe.unicopia.growing.instruction": "Se concentrez la magie de poney de terre", "item.unicopia.alicorn_badge": "Emblème d'alicorne", @@ -369,7 +369,7 @@ "effect.unicopia.fortification": "Fortification", "effect.unicopia.broken_wings": "Ailes cassées", "effect.unicopia.seaponys_ire": "Ire de Saponies", - "effect.unicopia.seaponys_grace": "Grâce des armes", + "effect.unicopia.seaponys_grace": "Grâce de l'océan", "effect.unicopia.change_race_earth": "Métamorphose de poney de terre", "effect.unicopia.change_race_unicorn": "Métamorphose de licorne", "effect.unicopia.change_race_pegasus": "Métamorphose de pégase", @@ -481,7 +481,7 @@ "spell.unicopia.flame": "Flamme", "spell.unicopia.flame.lore": "Cette gemme brûle chaudement avec une flamme magique", "spell.unicopia.infernal": "Incendie", - "spell.unicopia.infernal.lore": "Conjure l'essence même du Néant pour infuser ce monde", + "spell.unicopia.infernal.lore": "Conjurez l'essence même du Nether pour infuser ce monde", "spell.unicopia.fire_bolt": "Trait de feu", "spell.unicopia.fire_bolt.lore": "Produit plusieurs projectiles brûlants", "spell.unicopia.shield": "Protéger", @@ -710,7 +710,7 @@ "respawn.reason.joined_new_tribe": "%1$s est renaissé comme %2$s", "respawn.reason.illegal_race": "La course %s n'est pas autorisée par la configuration de votre serveur.", "tag.item.unicopia.groups.foraging": "Onglets créatifs : Foraging", - "tag.item.unicopia.groups.sea_pony": "Onglets créatifs : Seapony", + "tag.item.unicopia.groups.sea_pony": "Onglets créatifs : Poney de mer", "tag.item.unicopia.groups.earth_pony": "Onglets créatifs : Pony de la terre", "tag.item.unicopia.groups.bat_pony": "Onglets créatifs : Chauve-souris", "tag.item.unicopia.groups.changeling": "Onglets créatifs : Changement", @@ -1453,8 +1453,8 @@ "race.unicopia.kirin.alt": "Kirins", "race.unicopia.hippogriff": "Hippogriff", "race.unicopia.hippogriff.alt": "Hippogriffs", - "race.unicopia.seapony": "Pony de la mer", - "race.unicopia.seapony.alt": "Ponies de la mer", + "race.unicopia.seapony": "Poney de mer", + "race.unicopia.seapony.alt": "Poneys de mer", "death.attack.unicopia.generic.and_also": "%1$s et %2$s", "death.attack.unicopia.generic.whilst_flying": "%1$s en volant", "death.attack.unicopia.tribe_swap": "%1$s was reborn into a different tribe", @@ -1775,7 +1775,7 @@ "advancements.unicopia.love_is_power.description": "Bannir le Roi Sombra avec un cœur de cristal", "advancements.unicopia.hippogriff_route.title": "éclaboussure de Seaquestria", "advancements.unicopia.hippogriff_route.description": "Rejoignez le nid d'Hippogriff", - "advancements.unicopia.shoo_be_doo.title": "Shoo Be Doo!", + "advancements.unicopia.shoo_be_doo.title": "Shou Be Dou!", "advancements.unicopia.shoo_be_doo.description": "Utilisez un collier de perles pour vous transformer en créature marine.", "advancements.unicopia.shoo_be_done.title": "Le Shoo est fait !", "advancements.unicopia.shoo_be_done.description": "Utilisez un collier de perles pour revenir à la normale", From 21e06e5bbfdf699df49a528b0591527246b61c27 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Fri, 11 Oct 2024 03:31:06 +0100 Subject: [PATCH 072/110] New translations en_us.json (Chinese Simplified) --- src/main/resources/assets/unicopia/lang/zh_cn.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/unicopia/lang/zh_cn.json b/src/main/resources/assets/unicopia/lang/zh_cn.json index 405ca803..3e7d029f 100644 --- a/src/main/resources/assets/unicopia/lang/zh_cn.json +++ b/src/main/resources/assets/unicopia/lang/zh_cn.json @@ -790,8 +790,8 @@ "tag.item.farmersdelight.comfort_foods": "农民的Delight Comfort Food", "tag.item.trinkets.offhand.glove": "脱手Gloon Trinket", "tag.item.trinkets.hand.glove": "主手Gloon Trinket", - "tag.item.trinkets.chest.necklace": "Necklace", - "tag.item.trinkets.head.face": "面部Trinket", + "tag.item.trinkets.chest.necklace": "项链饰品", + "tag.item.trinkets.head.face": "面部饰品", "tag.item.sereneseasons.spring_crops": "Serene Seasons' Spring Crops", "tag.item.sereneseasons.summer_crops": "Serene Seasons' Summer Crops", "tag.item.sereneseasons.autumn_crops": "Serene Seasons' Autumn Crops", From 425219146079f630b8efb4fe857e807106986c42 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Fri, 11 Oct 2024 05:22:14 +0100 Subject: [PATCH 073/110] New translations en_us.json (Chinese Simplified) --- .../resources/assets/unicopia/lang/zh_cn.json | 144 +++++++++--------- 1 file changed, 72 insertions(+), 72 deletions(-) diff --git a/src/main/resources/assets/unicopia/lang/zh_cn.json b/src/main/resources/assets/unicopia/lang/zh_cn.json index 3e7d029f..b3135076 100644 --- a/src/main/resources/assets/unicopia/lang/zh_cn.json +++ b/src/main/resources/assets/unicopia/lang/zh_cn.json @@ -182,10 +182,10 @@ "item.unicopia.music_disc_popular": "音乐唱片", "item.unicopia.music_disc_crusade": "音乐唱片", "item.unicopia.music_disc_funk": "音乐唱片", - "jukebox_song.unicopia.pet": "Daniel Ingram - 宠物", - "jukebox_song.unicopia.popular": "Daniel Ingram - 受欢迎的", - "jukebox_song.unicopia.crusade": "Daniel Ingram - 十字线", - "jukebox_song.unicopia.funk": "有趣,只是有趣的", + "jukebox_song.unicopia.pet": "Daniel Ingram - pet", + "jukebox_song.unicopia.popular": "Daniel Ingram - popular", + "jukebox_song.unicopia.crusade": "Daniel Ingram - crusade", + "jukebox_song.unicopia.funk": "funk, just funk", "item.unicopia.cloud_lump": "云团", "item.unicopia.white_bed_sheets": "白色被单", "item.unicopia.light_gray_bed_sheets": "淡灰色被单", @@ -709,93 +709,93 @@ "gui.unicopia.page_num": "第%d页(共%d页)", "respawn.reason.joined_new_tribe": "%1$s 以一只 %2$s 的身份重生了", "respawn.reason.illegal_race": "%s这个种族目前不被你的服务器配置所允许", - "tag.item.unicopia.groups.foraging": "创造性标签:锻造模式", - "tag.item.unicopia.groups.sea_pony": "创造性标签:海普尼", + "tag.item.unicopia.groups.foraging": "创造栏:觅食", + "tag.item.unicopia.groups.sea_pony": "创造栏:海马", "tag.item.unicopia.groups.earth_pony": "Creative Tabs: Earth Pony", "tag.item.unicopia.groups.bat_pony": "Creative Tabs: Bat Pony", - "tag.item.unicopia.groups.changeling": "创意标签:更改", - "tag.item.unicopia.groups.pegasus": "创意标签:飞马座", + "tag.item.unicopia.groups.changeling": "创造栏:幻形灵", + "tag.item.unicopia.groups.pegasus": "创造栏:天马", "tag.item.unicopia.groups.unicorn": "Creative Tabs: Unicorn", - "tag.item.unicopia.forage.severe.prickly": "以很高的伤害几率成形了", - "tag.item.unicopia.forage.dangerous": "对堡垒的危险", - "tag.item.unicopia.forage.blinding": "变形几率变形", - "tag.item.unicopia.forage.nauseating": "用假冒的几率锻造的", - "tag.item.unicopia.forage.prickly": "有伤害几率被锻造的", - "tag.item.unicopia.forage.severe.nauseating": "用很高的恐慌几率锻造的", - "tag.item.unicopia.forage.risky": "带小风险成形的", - "tag.item.unicopia.forage.safe": "安全放置于福音", + "tag.item.unicopia.forage.severe.prickly": "吃了后有大概率产生害处", + "tag.item.unicopia.forage.dangerous": "危险别吃", + "tag.item.unicopia.forage.blinding": "吃了后有概率失明", + "tag.item.unicopia.forage.nauseating": "吃了后有概率反胃", + "tag.item.unicopia.forage.prickly": "吃了后有概率产生害处", + "tag.item.unicopia.forage.severe.nauseating": "吃了后大概率反胃", + "tag.item.unicopia.forage.risky": "吃了后有较小风险", + "tag.item.unicopia.forage.safe": "安全可食", "tag.item.unicopia.forage.filling": "安全到堡垒(填充)", - "tag.item.unicopia.forage.glowing": "随着发光变化而锻造。", - "tag.item.unicopia.forage.strengthening": "以强度的几率锻造了", - "tag.item.unicopia.food_types.high_quality_sea_vegetables": "高品质海蔬菜:", - "tag.item.unicopia.food_types.low_quality_sea_vegetables": "低品质海蔬菜数量", - "tag.item.unicopia.polearms": "极管", - "tag.item.unicopia.magic_feathers": "魔法病原体", - "tag.item.unicopia.can_cut_pie": "可以剪切Pie", + "tag.item.unicopia.forage.glowing": "吃了有概率全身发光", + "tag.item.unicopia.forage.strengthening": "吃了有概率力气变大", + "tag.item.unicopia.food_types.high_quality_sea_vegetables": "高品质海菜", + "tag.item.unicopia.food_types.low_quality_sea_vegetables": "低品质海菜", + "tag.item.unicopia.polearms": "长枪", + "tag.item.unicopia.magic_feathers": "魔法羽毛", + "tag.item.unicopia.can_cut_pie": "可以切派", "tag.item.unicopia.cloud_jars": "Cloud Jars", "tag.item.unicopia.baskets": "篮子", "tag.item.unicopia.shades": "影子", "tag.item.unicopia.shells": "外壳", "tag.item.unicopia.zap_logs": "Zap Apple Logs", - "tag.item.unicopia.spooked_mob_drops": "被被吹过的怪物掉下", - "tag.item.unicopia.wool_bed_sheets": "羊毛床板", - "tag.item.unicopia.is_delivered_aggressively": "正在递送的", + "tag.item.unicopia.spooked_mob_drops": "从被吓到的怪物身上掉落", + "tag.item.unicopia.wool_bed_sheets": "羊毛被单", + "tag.item.unicopia.is_delivered_aggressively": "不怀好意的快递", "tag.item.unicopia.cools_off_kirins": "Cools off kirins", "tag.item.unicopia.loot_bug_common_drops": "Common Loot Bug Drops", - "tag.item.unicopia.loot_bug_rare_drops": "Rare Loot Bug Drops", - "tag.item.unicopia.loot_bug_epic_drops": "Epic Loot Bug Drops", - "tag.item.unicopia.badges": "部落徽章", + "tag.item.unicopia.loot_bug_rare_drops": "稀有藏宝虫掉落物", + "tag.item.unicopia.loot_bug_epic_drops": "史诗藏宝虫掉落物", + "tag.item.unicopia.badges": "种族徽章", "tag.item.unicopia.apple_seeds": "苹果种子", - "tag.item.unicopia.bed_sheets": "床表", - "tag.item.unicopia.cloud_blocks": "云块", - "tag.item.unicopia.cloud_slabs": "云板", - "tag.item.unicopia.pies": "皮斯", - "tag.item.unicopia.palm_logs": "Palm Logs", + "tag.item.unicopia.bed_sheets": "被单", + "tag.item.unicopia.cloud_blocks": "云方块", + "tag.item.unicopia.cloud_slabs": "云台阶", + "tag.item.unicopia.pies": "馅饼", + "tag.item.unicopia.palm_logs": "棕榈木原木", "tag.item.unicopia.special_shells": "特殊的外壳", - "tag.item.unicopia.rock_stews": "Rock Stews", - "tag.item.unicopia.chitin_blocks": "甲壳块", + "tag.item.unicopia.rock_stews": "炖石头", + "tag.item.unicopia.chitin_blocks": "几丁质方块", "tag.item.unicopia.floats_on_clouds": "云端浮点数", - "tag.item.unicopia.falls_slowly": "花园放慢了", - "tag.item.unicopia.container_with_love": "填充爱容器", - "tag.item.unicopia.baked_goods": "面包商品", - "tag.item.unicopia.horse_shoes": "马马", - "tag.item.unicopia.cloud_beds": "云台", - "tag.item.unicopia.waxed_zap_logs": "波纹日志", + "tag.item.unicopia.falls_slowly": "缓慢下落", + "tag.item.unicopia.container_with_love": "装了爱的容器", + "tag.item.unicopia.baked_goods": "烘焙食品", + "tag.item.unicopia.horse_shoes": "马蹄铁", + "tag.item.unicopia.cloud_beds": "云床", + "tag.item.unicopia.waxed_zap_logs": "涂蜡魔虹苹果木原木", "tag.item.unicopia.cloud_stairs": "云楼梯", - "tag.item.unicopia.fresh_apples": "新鲜苹果", - "tag.item.unicopia.has_no_traits": "没有特性", - "tag.item.c.foods.acorn": "Acorns", + "tag.item.unicopia.fresh_apples": "新鲜的苹果", + "tag.item.unicopia.has_no_traits": "不含要素", + "tag.item.c.foods.acorn": "橡子", "tag.item.c.foods.apple": "苹果", - "tag.item.c.foods.dessert": "德塞斯", - "tag.item.c.foods.banana": "巴纳纳", - "tag.item.c.foods.pinecone": "调色器", - "tag.item.c.rocks": "岩石", - "tag.item.c.nuts": "努特斯", - "tag.item.c.worms": "蠕虫数", - "tag.item.c.foods.pineapple": "线性苹果", - "tag.item.c.foods.mushroom": "Mushroom", - "tag.item.c.foods.raw_insect": "原始Insects", + "tag.item.c.foods.dessert": "甜品", + "tag.item.c.foods.banana": "香蕉", + "tag.item.c.foods.pinecone": "松果", + "tag.item.c.rocks": "石块", + "tag.item.c.nuts": "坚果", + "tag.item.c.worms": "虫子", + "tag.item.c.foods.pineapple": "菠萝", + "tag.item.c.foods.mushroom": "菌类", + "tag.item.c.foods.raw_insect": "生的昆虫", "tag.item.c.coral_blocks": "珊瑚块", - "tag.item.c.foods.muffin": "静音", - "tag.item.c.foods.mango": "芒果文", - "tag.item.c.foods.rotten_meat": "旋转肉", - "tag.item.c.coral_fans": "珊瑚粉色", - "tag.item.c.corals": "Corals", - "tag.item.c.foods.rotten_insect": "旋转感染量", - "tag.item.c.foods.cooked_insect": "煮熟的昆特文", - "tag.item.c.foods.rotten_fish": "旋转鱼类", - "tag.item.c.foods.oatmeal": "美食类", - "tag.item.c.grain": "纹理", + "tag.item.c.foods.muffin": "玛芬", + "tag.item.c.foods.mango": "芒果", + "tag.item.c.foods.rotten_meat": "腐烂的肉", + "tag.item.c.coral_fans": "珊瑚扇", + "tag.item.c.corals": "珊瑚", + "tag.item.c.foods.rotten_insect": "腐烂的昆虫", + "tag.item.c.foods.cooked_insect": "烤过的昆虫", + "tag.item.c.foods.rotten_fish": "腐烂的鱼", + "tag.item.c.foods.oatmeal": "燕麦粥", + "tag.item.c.grain": "谷物", "tag.item.farmersdelight.cabbage_roll_ingredients": "农民的夜间客舱角色属性", - "tag.item.farmersdelight.comfort_foods": "农民的Delight Comfort Food", - "tag.item.trinkets.offhand.glove": "脱手Gloon Trinket", - "tag.item.trinkets.hand.glove": "主手Gloon Trinket", + "tag.item.farmersdelight.comfort_foods": "农夫乐事高热量食物", + "tag.item.trinkets.offhand.glove": "副手手套饰品", + "tag.item.trinkets.hand.glove": "主手手套饰品", "tag.item.trinkets.chest.necklace": "项链饰品", "tag.item.trinkets.head.face": "面部饰品", - "tag.item.sereneseasons.spring_crops": "Serene Seasons' Spring Crops", - "tag.item.sereneseasons.summer_crops": "Serene Seasons' Summer Crops", - "tag.item.sereneseasons.autumn_crops": "Serene Seasons' Autumn Crops", - "tag.item.sereneseasons.winter_crops": "Serene Seasons' Winter Crops", + "tag.item.sereneseasons.spring_crops": "静谧四季 春季作物", + "tag.item.sereneseasons.summer_crops": "静谧四季 夏季作物", + "tag.item.sereneseasons.autumn_crops": "静谧四季 秋季作物", + "tag.item.sereneseasons.winter_crops": "静谧四季 冬季作物", "gui.unicopia.tribe_selection.respawn": "你已经死了。", "gui.unicopia.tribe_selection.respawn.journey": "但结束不是全部,因为每个结束的尽头都是另一个开始。", "gui.unicopia.tribe_selection.respawn.choice": "请明智地选择,因为你现在做出的选择将改变你周遭的世界和你可能走的道路。", @@ -805,7 +805,7 @@ "gui.unicopia.tribe_selection.preference": "您当前的首选种族设置为 %s。", "gui.unicopia.tribe_selection.options": "可用种族:", "gui.unicopia.tribe_selection.options.disabled": "选项不可用", - "gui.unicopia.tribe_selection.describe.unicopia.human": "单独访问", + "gui.unicopia.tribe_selection.describe.unicopia.human": "唯有自己", "gui.unicopia.tribe_selection.describe.unicopia.earth": "加入陆马族", "gui.unicopia.tribe_selection.describe.unicopia.unicorn": "加入独角兽族,精通奥术魔法", "gui.unicopia.tribe_selection.describe.unicopia.pegasus": "加入天马族,与闪电天马一起翱翔", From 1a7865951709ad399d7980c5adf0501383b689c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Fri, 11 Oct 2024 09:54:43 +0100 Subject: [PATCH 074/110] New translations en_us.json (Chinese Traditional) --- .../resources/assets/unicopia/lang/zh_tw.json | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/src/main/resources/assets/unicopia/lang/zh_tw.json b/src/main/resources/assets/unicopia/lang/zh_tw.json index 9a9dd9a1..147216cd 100644 --- a/src/main/resources/assets/unicopia/lang/zh_tw.json +++ b/src/main/resources/assets/unicopia/lang/zh_tw.json @@ -541,7 +541,7 @@ "spell_attribute.unicopia.soapiness": "皂度", "spell_attribute.unicopia.velocity": "速度", "spell_attribute.unicopia.vertical_velocity": "初始發射速度", - "spell_attribute.unicopia.hang_time": "Hang Time", + "spell_attribute.unicopia.hang_time": "懸空時間", "spell_attribute.unicopia.pushing_power": "推力", "spell_attribute.unicopia.damage_to_target": "目標傷害", "spell_attribute.unicopia.simultanious_targets": "並擊目標", @@ -550,7 +550,7 @@ "spell_attribute.unicopia.projectile_count": "投射物數量", "spell_attribute.unicopia.follow_range": "追蹤距離", "spell_attribute.unicopia.stick_to_target": "貼附於目標", - "spell_attribute.unicopia.orb_count": "Orb Count", + "spell_attribute.unicopia.orb_count": "光球數量", "spell_attribute.unicopia.wave_size": "波浪大小", "spell_attribute.unicopia.target_preference": "目標偏好", "spell_attribute.unicopia.caster_preference": "咒師偏好", @@ -694,9 +694,9 @@ "ability.unicopia.sonar_pulse": "聲納脈衝", "affinity.unicopia.good": "良好", "affinity.unicopia.bad": "惡劣", - "affinity.unicopia.neutral": "Neutral", - "affinity.unicopia.when_cast": "When Cast:", - "affinity.unicopia.corruption": "Corruption", + "affinity.unicopia.neutral": "適中", + "affinity.unicopia.when_cast": "當施咒時:", + "affinity.unicopia.corruption": "墮落", "gui.unicopia.trait.label": "%s之元", "gui.unicopia.trait.group": "\n %s", "gui.unicopia.trait.corruption": "\n %s墮落", @@ -709,13 +709,13 @@ "gui.unicopia.page_num": "%d頁,共%d頁", "respawn.reason.joined_new_tribe": "%1$s轉生爲%2$s", "respawn.reason.illegal_race": "%s種族並不被您所在伺服器的設定允許。", - "tag.item.unicopia.groups.foraging": "Creative Tabs: Foraging", - "tag.item.unicopia.groups.sea_pony": "Creative Tabs: Seapony", - "tag.item.unicopia.groups.earth_pony": "Creative Tabs: Earth Pony", - "tag.item.unicopia.groups.bat_pony": "Creative Tabs: Bat Pony", - "tag.item.unicopia.groups.changeling": "Creative Tabs: Changeling", - "tag.item.unicopia.groups.pegasus": "Creative Tabs: Pegasus", - "tag.item.unicopia.groups.unicorn": "Creative Tabs: Unicorn", + "tag.item.unicopia.groups.foraging": "創造模式分頁:覓食", + "tag.item.unicopia.groups.sea_pony": "創造模式分頁:海馬", + "tag.item.unicopia.groups.earth_pony": "創造模式分頁:陸馬", + "tag.item.unicopia.groups.bat_pony": "創造模式分頁:夜騏", + "tag.item.unicopia.groups.changeling": "創造模式分頁:幻形", + "tag.item.unicopia.groups.pegasus": "創造模式分頁:飛馬", + "tag.item.unicopia.groups.unicorn": "創造模式分頁:獨角", "tag.item.unicopia.forage.severe.prickly": "Foraged with high chance of harming", "tag.item.unicopia.forage.dangerous": "Dangerous to Forage", "tag.item.unicopia.forage.blinding": "Foraged with chance to blinding", @@ -723,12 +723,12 @@ "tag.item.unicopia.forage.prickly": "Foraged with chance of harm", "tag.item.unicopia.forage.severe.nauseating": "Foraged with high chance of nausea", "tag.item.unicopia.forage.risky": "Foraged with Minor Risk", - "tag.item.unicopia.forage.safe": "Safe to Forage", - "tag.item.unicopia.forage.filling": "Safe to Forage (Filling)", + "tag.item.unicopia.forage.safe": "可安心食用", + "tag.item.unicopia.forage.filling": "可安心食用(十分飽腹)", "tag.item.unicopia.forage.glowing": "Foraged with change of glowing", "tag.item.unicopia.forage.strengthening": "Foraged with chance of strength", - "tag.item.unicopia.food_types.high_quality_sea_vegetables": "High Quality Sea Vegetables", - "tag.item.unicopia.food_types.low_quality_sea_vegetables": "Low Quality Sea Vegetables", + "tag.item.unicopia.food_types.high_quality_sea_vegetables": "高質素海藻", + "tag.item.unicopia.food_types.low_quality_sea_vegetables": "低質素海藻", "tag.item.unicopia.polearms": "Polearms", "tag.item.unicopia.magic_feathers": "Magic Feathers", "tag.item.unicopia.can_cut_pie": "Can Cut Pie", @@ -736,7 +736,7 @@ "tag.item.unicopia.baskets": "Baskets", "tag.item.unicopia.shades": "Shades", "tag.item.unicopia.shells": "Shells", - "tag.item.unicopia.zap_logs": "Zap Apple Logs", + "tag.item.unicopia.zap_logs": "彩虹蘋果原木", "tag.item.unicopia.spooked_mob_drops": "Dropped by spooked mobs", "tag.item.unicopia.wool_bed_sheets": "Wool bed Sheets", "tag.item.unicopia.is_delivered_aggressively": "Aggressively Delivered", @@ -760,7 +760,7 @@ "tag.item.unicopia.baked_goods": "Baked Goods", "tag.item.unicopia.horse_shoes": "Horseshoes", "tag.item.unicopia.cloud_beds": "Cloud beds", - "tag.item.unicopia.waxed_zap_logs": "Waxed Zap Logs", + "tag.item.unicopia.waxed_zap_logs": "上蠟彩虹蘋果原木", "tag.item.unicopia.cloud_stairs": "Cloud Stairs", "tag.item.unicopia.fresh_apples": "Fresh Apples", "tag.item.unicopia.has_no_traits": "Has No Traits", From 01a54620ade9cd900556a246aad7f3f4ee95dc26 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Fri, 11 Oct 2024 12:13:01 +0100 Subject: [PATCH 075/110] New translations en_us.json (Chinese Traditional) --- .../resources/assets/unicopia/lang/zh_tw.json | 156 +++++++++--------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/src/main/resources/assets/unicopia/lang/zh_tw.json b/src/main/resources/assets/unicopia/lang/zh_tw.json index 147216cd..454ab64a 100644 --- a/src/main/resources/assets/unicopia/lang/zh_tw.json +++ b/src/main/resources/assets/unicopia/lang/zh_tw.json @@ -716,86 +716,86 @@ "tag.item.unicopia.groups.changeling": "創造模式分頁:幻形", "tag.item.unicopia.groups.pegasus": "創造模式分頁:飛馬", "tag.item.unicopia.groups.unicorn": "創造模式分頁:獨角", - "tag.item.unicopia.forage.severe.prickly": "Foraged with high chance of harming", - "tag.item.unicopia.forage.dangerous": "Dangerous to Forage", - "tag.item.unicopia.forage.blinding": "Foraged with chance to blinding", - "tag.item.unicopia.forage.nauseating": "Foraged with chance of nausea", - "tag.item.unicopia.forage.prickly": "Foraged with chance of harm", - "tag.item.unicopia.forage.severe.nauseating": "Foraged with high chance of nausea", - "tag.item.unicopia.forage.risky": "Foraged with Minor Risk", + "tag.item.unicopia.forage.severe.prickly": "食用後有很高機率受傷害", + "tag.item.unicopia.forage.dangerous": "食用有危險", + "tag.item.unicopia.forage.blinding": "食用後有機率致盲", + "tag.item.unicopia.forage.nauseating": "食用後有機率噁心", + "tag.item.unicopia.forage.prickly": "食用後有機率受傷害", + "tag.item.unicopia.forage.severe.nauseating": "食用後有很高機率噁心", + "tag.item.unicopia.forage.risky": "食用有輕度風險", "tag.item.unicopia.forage.safe": "可安心食用", "tag.item.unicopia.forage.filling": "可安心食用(十分飽腹)", - "tag.item.unicopia.forage.glowing": "Foraged with change of glowing", - "tag.item.unicopia.forage.strengthening": "Foraged with chance of strength", + "tag.item.unicopia.forage.glowing": "食用後有機率發光", + "tag.item.unicopia.forage.strengthening": "食用後有機率強健", "tag.item.unicopia.food_types.high_quality_sea_vegetables": "高質素海藻", "tag.item.unicopia.food_types.low_quality_sea_vegetables": "低質素海藻", - "tag.item.unicopia.polearms": "Polearms", - "tag.item.unicopia.magic_feathers": "Magic Feathers", - "tag.item.unicopia.can_cut_pie": "Can Cut Pie", - "tag.item.unicopia.cloud_jars": "Cloud Jars", - "tag.item.unicopia.baskets": "Baskets", + "tag.item.unicopia.polearms": "長柄武器", + "tag.item.unicopia.magic_feathers": "魔羽", + "tag.item.unicopia.can_cut_pie": "可用於切派", + "tag.item.unicopia.cloud_jars": "雲朵罐", + "tag.item.unicopia.baskets": "籃子", "tag.item.unicopia.shades": "Shades", - "tag.item.unicopia.shells": "Shells", + "tag.item.unicopia.shells": "殼", "tag.item.unicopia.zap_logs": "彩虹蘋果原木", - "tag.item.unicopia.spooked_mob_drops": "Dropped by spooked mobs", - "tag.item.unicopia.wool_bed_sheets": "Wool bed Sheets", - "tag.item.unicopia.is_delivered_aggressively": "Aggressively Delivered", - "tag.item.unicopia.cools_off_kirins": "Cools off kirins", - "tag.item.unicopia.loot_bug_common_drops": "Common Loot Bug Drops", - "tag.item.unicopia.loot_bug_rare_drops": "Rare Loot Bug Drops", - "tag.item.unicopia.loot_bug_epic_drops": "Epic Loot Bug Drops", - "tag.item.unicopia.badges": "Tribe Badges", - "tag.item.unicopia.apple_seeds": "Apple Seeds", - "tag.item.unicopia.bed_sheets": "Bed Sheets", - "tag.item.unicopia.cloud_blocks": "Cloud Blocks", - "tag.item.unicopia.cloud_slabs": "Cloud Slabs", - "tag.item.unicopia.pies": "Pies", - "tag.item.unicopia.palm_logs": "Palm Logs", - "tag.item.unicopia.special_shells": "Special Shells", - "tag.item.unicopia.rock_stews": "Rock Stews", - "tag.item.unicopia.chitin_blocks": "Chitin Blocks", - "tag.item.unicopia.floats_on_clouds": "Floats on Clouds", - "tag.item.unicopia.falls_slowly": "Falls Slowly", - "tag.item.unicopia.container_with_love": "Filled Love Container", - "tag.item.unicopia.baked_goods": "Baked Goods", - "tag.item.unicopia.horse_shoes": "Horseshoes", - "tag.item.unicopia.cloud_beds": "Cloud beds", + "tag.item.unicopia.spooked_mob_drops": "由受驚的生物掉落", + "tag.item.unicopia.wool_bed_sheets": "羊毛被單", + "tag.item.unicopia.is_delivered_aggressively": "十分激進地送達", + "tag.item.unicopia.cools_off_kirins": "可讓麒麟冷靜", + "tag.item.unicopia.loot_bug_common_drops": "常見聚寶蟲掉落物", + "tag.item.unicopia.loot_bug_rare_drops": "稀有聚寶蟲掉落物", + "tag.item.unicopia.loot_bug_epic_drops": "史詩聚寶蟲掉落物", + "tag.item.unicopia.badges": "種族徽章", + "tag.item.unicopia.apple_seeds": "蘋果種子", + "tag.item.unicopia.bed_sheets": "被單", + "tag.item.unicopia.cloud_blocks": "雲朵方塊", + "tag.item.unicopia.cloud_slabs": "雲朵半磚", + "tag.item.unicopia.pies": "餡餅", + "tag.item.unicopia.palm_logs": "棕櫚原木", + "tag.item.unicopia.special_shells": "特殊螺殼", + "tag.item.unicopia.rock_stews": "燉石湯", + "tag.item.unicopia.chitin_blocks": "蟲殼方塊", + "tag.item.unicopia.floats_on_clouds": "可浮於雲上", + "tag.item.unicopia.falls_slowly": "緩慢掉落", + "tag.item.unicopia.container_with_love": "充滿愛意的容器", + "tag.item.unicopia.baked_goods": "烘培食品", + "tag.item.unicopia.horse_shoes": "蹄鐵", + "tag.item.unicopia.cloud_beds": "雲床", "tag.item.unicopia.waxed_zap_logs": "上蠟彩虹蘋果原木", - "tag.item.unicopia.cloud_stairs": "Cloud Stairs", - "tag.item.unicopia.fresh_apples": "Fresh Apples", - "tag.item.unicopia.has_no_traits": "Has No Traits", - "tag.item.c.foods.acorn": "Acorns", - "tag.item.c.foods.apple": "Apples", - "tag.item.c.foods.dessert": "Desserts", - "tag.item.c.foods.banana": "Bananas", - "tag.item.c.foods.pinecone": "Pinecones", - "tag.item.c.rocks": "Rocks", - "tag.item.c.nuts": "Nuts", - "tag.item.c.worms": "Worms", - "tag.item.c.foods.pineapple": "Pineapples", - "tag.item.c.foods.mushroom": "Mushrooms", - "tag.item.c.foods.raw_insect": "Raw Insects", - "tag.item.c.coral_blocks": "Coral Blocks", - "tag.item.c.foods.muffin": "Muffins", - "tag.item.c.foods.mango": "Mangoes", - "tag.item.c.foods.rotten_meat": "Rotten Meat", - "tag.item.c.coral_fans": "Coral Fans", - "tag.item.c.corals": "Corals", - "tag.item.c.foods.rotten_insect": "Rotten Insects", - "tag.item.c.foods.cooked_insect": "Cooked Insect", - "tag.item.c.foods.rotten_fish": "Rotten Fish", - "tag.item.c.foods.oatmeal": "Oatmeals", - "tag.item.c.grain": "Grain", - "tag.item.farmersdelight.cabbage_roll_ingredients": "Farmer's Delight Cabbage Roll Ingredients", - "tag.item.farmersdelight.comfort_foods": "Farmer's Delight Comfort Foods", - "tag.item.trinkets.offhand.glove": "Offhand Glove Trinket", - "tag.item.trinkets.hand.glove": "Mainhand Glove Trinket", - "tag.item.trinkets.chest.necklace": "Necklace Trinket", - "tag.item.trinkets.head.face": "Face Trinket", - "tag.item.sereneseasons.spring_crops": "Serene Seasons' Spring Crops", - "tag.item.sereneseasons.summer_crops": "Serene Seasons' Summer Crops", - "tag.item.sereneseasons.autumn_crops": "Serene Seasons' Autumn Crops", - "tag.item.sereneseasons.winter_crops": "Serene Seasons' Winter Crops", + "tag.item.unicopia.cloud_stairs": "雲朵階梯", + "tag.item.unicopia.fresh_apples": "新鮮蘋果", + "tag.item.unicopia.has_no_traits": "無特性", + "tag.item.c.foods.acorn": "橡實", + "tag.item.c.foods.apple": "蘋果", + "tag.item.c.foods.dessert": "甜點", + "tag.item.c.foods.banana": "香蕉", + "tag.item.c.foods.pinecone": "松果", + "tag.item.c.rocks": "岩石", + "tag.item.c.nuts": "堅果", + "tag.item.c.worms": "蠕蟲", + "tag.item.c.foods.pineapple": "鳳梨", + "tag.item.c.foods.mushroom": "蘑菇", + "tag.item.c.foods.raw_insect": "生昆蟲", + "tag.item.c.coral_blocks": "珊瑚塊", + "tag.item.c.foods.muffin": "小鬆餅", + "tag.item.c.foods.mango": "芒果", + "tag.item.c.foods.rotten_meat": "腐肉", + "tag.item.c.coral_fans": "氣泡珊瑚", + "tag.item.c.corals": "珊瑚", + "tag.item.c.foods.rotten_insect": "腐爛昆蟲", + "tag.item.c.foods.cooked_insect": "熟昆蟲", + "tag.item.c.foods.rotten_fish": "腐魚", + "tag.item.c.foods.oatmeal": "燕麥片", + "tag.item.c.grain": "穀物", + "tag.item.farmersdelight.cabbage_roll_ingredients": "農夫樂事高麗菜捲成分", + "tag.item.farmersdelight.comfort_foods": "農夫樂事療愈食物", + "tag.item.trinkets.offhand.glove": "非慣用手配飾", + "tag.item.trinkets.hand.glove": "慣用手配飾", + "tag.item.trinkets.chest.necklace": "脖頸配飾", + "tag.item.trinkets.head.face": "臉部配飾", + "tag.item.sereneseasons.spring_crops": "靜謐四季春季作物", + "tag.item.sereneseasons.summer_crops": "靜謐四季夏季作物", + "tag.item.sereneseasons.autumn_crops": "靜謐四季秋季作物", + "tag.item.sereneseasons.winter_crops": "靜謐四季冬季作物", "gui.unicopia.tribe_selection.respawn": "你已經死了。", "gui.unicopia.tribe_selection.respawn.journey": "但這個結束並非是一切的終結;每個結束的末尾都是一個新的開始。", "gui.unicopia.tribe_selection.respawn.choice": "謹慎地選擇吧,你現在的選擇將會改變你週遭的世界,也會改變你所選擇的路。", @@ -805,7 +805,7 @@ "gui.unicopia.tribe_selection.preference": "你當前的偏好種族已設爲%s。", "gui.unicopia.tribe_selection.options": "可選種族:", "gui.unicopia.tribe_selection.options.disabled": "選項不可用", - "gui.unicopia.tribe_selection.describe.unicopia.human": "Go it alone", + "gui.unicopia.tribe_selection.describe.unicopia.human": "特立獨行", "gui.unicopia.tribe_selection.describe.unicopia.earth": "成爲陸馬,擁抱自然的魔力", "gui.unicopia.tribe_selection.describe.unicopia.unicorn": "成爲獨角,掌握魔法的藝術", "gui.unicopia.tribe_selection.describe.unicopia.pegasus": "成爲飛馬,在空中自由翱翔", @@ -902,7 +902,7 @@ "gui.unicopia.spellbook.chapter.artefacts.status.unconfirmed": "狀態:未確認", "gui.unicopia.spellbook.chapter.artefacts.status.confirmed": "狀態:已確認", "gui.unicopia.spellbook.chapter.artefacts.status.lost": "狀態:已遺失", - "gui.unicopia.spellbook.chapter.introduction.p1.title": "Preface", + "gui.unicopia.spellbook.chapter.introduction.p1.title": "前言", "gui.unicopia.spellbook.chapter.introduction.p1.body": "To whomever holds this tome, beware what you seek for you might not like what you find. §kHither yonder equs§r.", "gui.unicopia.spellbook.chapter.introduction.p2.title": "Ch.1 Magic in Equestria", "gui.unicopia.spellbook.chapter.introduction.p2.body": "Equestria is filled with magic of all different shapes and forms. Following recent events, however, it's has become plainly obvious that we do not fully understand all that there is about the world of Equestria. That is why the crown has tasked me with researching Magic in all of its forms, so we might utilise it and, I hope, save ourselves from the §kdiscordic assault§r.", @@ -1344,9 +1344,9 @@ "key.unicopia.secondary": "次要能力", "key.unicopia.tertiary": "第三能力", "key.unicopia.passive": "被動能力", - "key.unicopia.ability_modifier_tap": "VR Ability Modifier (1-TAP)", - "key.unicopia.ability_modifier_double_tap": "VR Ability Modifier (2-TAP)", - "key.unicopia.ability_modifier_triple_tap": "VR Ability Modifier (3-TAP)", + "key.unicopia.ability_modifier_tap": "虛擬實境技能修飾(單擊)", + "key.unicopia.ability_modifier_double_tap": "虛擬實境技能修飾(雙擊)", + "key.unicopia.ability_modifier_triple_tap": "虛擬實境技能修飾(三擊)", "key.unicopia.hud_page_dn": "介面上一頁", "key.unicopia.hud_page_up": "介面下一頁", "enchantment.unicopia.gem_finder": "尋礦", From 405732e975ead456e0514aa289ef28de99ebcdaf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Fri, 11 Oct 2024 14:58:43 +0100 Subject: [PATCH 076/110] New translations en_us.json (Chinese Simplified) --- .../resources/assets/unicopia/lang/zh_cn.json | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/resources/assets/unicopia/lang/zh_cn.json b/src/main/resources/assets/unicopia/lang/zh_cn.json index b3135076..e1ba96f5 100644 --- a/src/main/resources/assets/unicopia/lang/zh_cn.json +++ b/src/main/resources/assets/unicopia/lang/zh_cn.json @@ -711,11 +711,11 @@ "respawn.reason.illegal_race": "%s这个种族目前不被你的服务器配置所允许", "tag.item.unicopia.groups.foraging": "创造栏:觅食", "tag.item.unicopia.groups.sea_pony": "创造栏:海马", - "tag.item.unicopia.groups.earth_pony": "Creative Tabs: Earth Pony", - "tag.item.unicopia.groups.bat_pony": "Creative Tabs: Bat Pony", + "tag.item.unicopia.groups.earth_pony": "创造栏:陆马", + "tag.item.unicopia.groups.bat_pony": "创造栏:夜骐", "tag.item.unicopia.groups.changeling": "创造栏:幻形灵", "tag.item.unicopia.groups.pegasus": "创造栏:天马", - "tag.item.unicopia.groups.unicorn": "Creative Tabs: Unicorn", + "tag.item.unicopia.groups.unicorn": "创造栏:独角兽", "tag.item.unicopia.forage.severe.prickly": "吃了后有大概率产生害处", "tag.item.unicopia.forage.dangerous": "危险别吃", "tag.item.unicopia.forage.blinding": "吃了后有概率失明", @@ -731,17 +731,17 @@ "tag.item.unicopia.food_types.low_quality_sea_vegetables": "低品质海菜", "tag.item.unicopia.polearms": "长枪", "tag.item.unicopia.magic_feathers": "魔法羽毛", - "tag.item.unicopia.can_cut_pie": "可以切派", - "tag.item.unicopia.cloud_jars": "Cloud Jars", + "tag.item.unicopia.can_cut_pie": "可以用于切派", + "tag.item.unicopia.cloud_jars": "装了云的罐子", "tag.item.unicopia.baskets": "篮子", "tag.item.unicopia.shades": "影子", - "tag.item.unicopia.shells": "外壳", - "tag.item.unicopia.zap_logs": "Zap Apple Logs", + "tag.item.unicopia.shells": "贝壳类", + "tag.item.unicopia.zap_logs": "魔虹苹果木原木", "tag.item.unicopia.spooked_mob_drops": "从被吓到的怪物身上掉落", "tag.item.unicopia.wool_bed_sheets": "羊毛被单", "tag.item.unicopia.is_delivered_aggressively": "不怀好意的快递", - "tag.item.unicopia.cools_off_kirins": "Cools off kirins", - "tag.item.unicopia.loot_bug_common_drops": "Common Loot Bug Drops", + "tag.item.unicopia.cools_off_kirins": "用来冷却麒麟", + "tag.item.unicopia.loot_bug_common_drops": "寻常藏宝虫掉落物", "tag.item.unicopia.loot_bug_rare_drops": "稀有藏宝虫掉落物", "tag.item.unicopia.loot_bug_epic_drops": "史诗藏宝虫掉落物", "tag.item.unicopia.badges": "种族徽章", @@ -751,10 +751,10 @@ "tag.item.unicopia.cloud_slabs": "云台阶", "tag.item.unicopia.pies": "馅饼", "tag.item.unicopia.palm_logs": "棕榈木原木", - "tag.item.unicopia.special_shells": "特殊的外壳", + "tag.item.unicopia.special_shells": "特殊的贝壳", "tag.item.unicopia.rock_stews": "炖石头", "tag.item.unicopia.chitin_blocks": "几丁质方块", - "tag.item.unicopia.floats_on_clouds": "云端浮点数", + "tag.item.unicopia.floats_on_clouds": "浮在云上", "tag.item.unicopia.falls_slowly": "缓慢下落", "tag.item.unicopia.container_with_love": "装了爱的容器", "tag.item.unicopia.baked_goods": "烘焙食品", From c2d698c3c2982e959ef2206d0d0754db3b8cc4f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 12 Oct 2024 13:49:57 +0100 Subject: [PATCH 077/110] New translations en_us.json (French) --- .../resources/assets/unicopia/lang/fr_fr.json | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/main/resources/assets/unicopia/lang/fr_fr.json b/src/main/resources/assets/unicopia/lang/fr_fr.json index c1cfc8ea..df6192a7 100644 --- a/src/main/resources/assets/unicopia/lang/fr_fr.json +++ b/src/main/resources/assets/unicopia/lang/fr_fr.json @@ -59,7 +59,7 @@ "item.unicopia.sweet_apple": "Pomme sucrée", "item.unicopia.sour_apple": "Pomme aigre", "item.unicopia.rotten_apple": "Pomme putréfiée", - "item.unicopia.cooked_zap_apple": "Zap apple cuite", + "item.unicopia.cooked_zap_apple": "Pomme zap cuite", "item.unicopia.zap_apple": "Pomme zap", "item.unicopia.zap_bulb": "Pomme zap inégal", "item.unicopia.rotten_cod": "Morue Pourrie", @@ -86,7 +86,7 @@ "item.unicopia.lightning_jar": "Foudre dans un bocal", "block.unicopia.lightning_jar": "Foudre dans un bocal", "item.unicopia.zap_apple_jam_jar": "Confiture de pomme zap", - "block.unicopia.zap_jar": "Jar de Confiture de Zap Apple", + "block.unicopia.zap_jar": "Bocal de confiture de pomme zap", "item.unicopia.toast": "Pain grillé", "item.unicopia.burned_toast": "Pain brûlé", "item.unicopia.jam_toast": "Pain grillé à la confiture de pomme zap", @@ -185,7 +185,7 @@ "jukebox_song.unicopia.pet": "Daniel Ingram - pet", "jukebox_song.unicopia.popular": "Daniel Ingram - popular", "jukebox_song.unicopia.crusade": "Daniel Ingram - crusade", - "jukebox_song.unicopia.funk": "funk, juste funk", + "jukebox_song.unicopia.funk": "funk, just funk", "item.unicopia.cloud_lump": "Morceau du Nuage", "item.unicopia.white_bed_sheets": "Lits Blancs", "item.unicopia.light_gray_bed_sheets": "Lits de lit gris clair", @@ -219,23 +219,23 @@ "block.unicopia.bananas": "Bananes", "block.unicopia.zapling": "Zapling", "block.unicopia.potted_zapling": "Zapling en pot", - "block.unicopia.zap_log": "Confiture de Zap Apple", - "block.unicopia.zap_wood": "Zap Bois de Pomme", - "block.unicopia.stripped_zap_log": "Journal d'Apple Zap Stripped", - "block.unicopia.stripped_zap_wood": "Bois de pomme Zap rayé", - "block.unicopia.zap_planks": "Planches de pomme Zap", - "block.unicopia.zap_stairs": "Escalier de Pomme Zap", - "block.unicopia.zap_slab": "Dalle de Pomme Zap", - "block.unicopia.zap_fence": "Barrière en Zap Pomme", - "block.unicopia.zap_fence_gate": "Portillon en Zap Pomme", - "block.unicopia.waxed_zap_log": "Journal d'Pomme Zap Caxé", - "block.unicopia.waxed_zap_wood": "Bois de Pomme Zap Ciré", - "block.unicopia.waxed_stripped_zap_log": "Journal d'Pomme Zap Ciré", - "block.unicopia.waxed_stripped_zap_wood": "Pomme Zap en Bois de Pomme Ciré", - "block.unicopia.waxed_zap_planks": "Planches de Pomme Zap Ciré", + "block.unicopia.zap_log": "Bûche de pomme zap", + "block.unicopia.zap_wood": "Bois de pomme zap", + "block.unicopia.stripped_zap_log": "Bûche de pomme zap écorcé", + "block.unicopia.stripped_zap_wood": "Bois de pomme zap écorcé", + "block.unicopia.zap_planks": "Planches de pomme zap", + "block.unicopia.zap_stairs": "Escalier en pomme zap", + "block.unicopia.zap_slab": "Dalle en pomme zap", + "block.unicopia.zap_fence": "Barrière en pomme zap", + "block.unicopia.zap_fence_gate": "Portillon en pomme zap", + "block.unicopia.waxed_zap_log": "Bûche de pomme zap ciré", + "block.unicopia.waxed_zap_wood": "Bois de pomme zap ciré", + "block.unicopia.waxed_stripped_zap_log": "Bûche de pomme zap écorcé ciré", + "block.unicopia.waxed_stripped_zap_wood": "Bois de pomme zap écorcé ciré", + "block.unicopia.waxed_zap_planks": "Planches de pomme zap ciré", "block.unicopia.waxed_zap_stairs": "Escaliers de Pomme Zap Ciré", - "block.unicopia.waxed_zap_slab": "Dalle de pomme Zap Ciré", - "block.unicopia.waxed_zap_fence": "Clôture de Pomme Zap Cirée", + "block.unicopia.waxed_zap_slab": "Dalle en pomme zap ciré", + "block.unicopia.waxed_zap_fence": "Barrière en pomme zap ciré", "block.unicopia.waxed_zap_fence_gate": "Portail de Clôture de Pomme Zap en Cire", "block.unicopia.zap_leaves": "Zap Feuilles de Pomme", "block.unicopia.flowering_zap_leaves": "Feuilles d'Pomme Zap Florissantes", From 5cb958af18616ca8e6a7e5cefd6cb0cd6a36a101 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 12 Oct 2024 15:01:21 +0100 Subject: [PATCH 078/110] New translations en_us.json (French) --- .../resources/assets/unicopia/lang/fr_fr.json | 30 +++++++++---------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/src/main/resources/assets/unicopia/lang/fr_fr.json b/src/main/resources/assets/unicopia/lang/fr_fr.json index df6192a7..e3432376 100644 --- a/src/main/resources/assets/unicopia/lang/fr_fr.json +++ b/src/main/resources/assets/unicopia/lang/fr_fr.json @@ -236,11 +236,11 @@ "block.unicopia.waxed_zap_stairs": "Escaliers de Pomme Zap Ciré", "block.unicopia.waxed_zap_slab": "Dalle en pomme zap ciré", "block.unicopia.waxed_zap_fence": "Barrière en pomme zap ciré", - "block.unicopia.waxed_zap_fence_gate": "Portail de Clôture de Pomme Zap en Cire", - "block.unicopia.zap_leaves": "Zap Feuilles de Pomme", - "block.unicopia.flowering_zap_leaves": "Feuilles d'Pomme Zap Florissantes", - "block.unicopia.zap_apple": "Zap Pomme", - "block.unicopia.zap_bulb": "Zap Pomme Inégal", + "block.unicopia.waxed_zap_fence_gate": "Portillon en pomme zap ciré", + "block.unicopia.zap_leaves": "Feuilles de pomme zap", + "block.unicopia.flowering_zap_leaves": "Feuilles de pomme zap fleurie", + "block.unicopia.zap_apple": "Pomme zap", + "block.unicopia.zap_bulb": "Pomme zap inégale", "block.unicopia.palm_sapling": "Pousse de Palmier", "block.unicopia.potted_palm_sapling": "Pousse de Paume en Pot", "block.unicopia.palm_log": "Bûche de Palme", @@ -531,16 +531,16 @@ "spell_attribute.unicopia.affects.blocks": "Affecte uniquement les blocs", "spell_attribute.unicopia.follows_target": "S'abonner à la cible", "spell_attribute.unicopia.causes_levitation": "Cause lévitation", - "spell_attribute.unicopia.permit_items": "Permits Items", + "spell_attribute.unicopia.permit_items": " Permettez d'objets", "spell_attribute.unicopia.permit_passive": "Autorise les monstres passifs", "spell_attribute.unicopia.permit_hostile": "Permettre les monstres hostiles", - "spell_attribute.unicopia.permit_player": "Permits Other Players", + "spell_attribute.unicopia.permit_player": " Permettez d'autres joueurs", "spell_attribute.unicopia.range": "Portée de l'effet", "spell_attribute.unicopia.duration": "Durée de l'effet", "spell_attribute.unicopia.strength": "Force de l'effet", "spell_attribute.unicopia.soapiness": "Sévérité", "spell_attribute.unicopia.velocity": "Vitesse", - "spell_attribute.unicopia.vertical_velocity": "Launch Speed", + "spell_attribute.unicopia.vertical_velocity": "Vitesse initiale de lancement", "spell_attribute.unicopia.hang_time": "Temps de suspension", "spell_attribute.unicopia.pushing_power": "Pousser", "spell_attribute.unicopia.damage_to_target": "Dégâts sur la cible", @@ -696,7 +696,7 @@ "affinity.unicopia.bad": "Mauvais", "affinity.unicopia.neutral": "Neutre", "affinity.unicopia.when_cast": "Quand lancé:", - "affinity.unicopia.corruption": " %s%.2f Corruption", + "affinity.unicopia.corruption": "Corruption", "gui.unicopia.trait.label": "Élément de %s", "gui.unicopia.trait.group": "\n %s", "gui.unicopia.trait.corruption": "\nCorruption de %s", @@ -736,7 +736,7 @@ "tag.item.unicopia.baskets": "Paniers", "tag.item.unicopia.shades": "Nuances", "tag.item.unicopia.shells": "Obus", - "tag.item.unicopia.zap_logs": "Apple Apple Logs", + "tag.item.unicopia.zap_logs": "Bûches de pomme zap", "tag.item.unicopia.spooked_mob_drops": "Lâché par les créatures effrayées", "tag.item.unicopia.wool_bed_sheets": "Linge de lit en laine", "tag.item.unicopia.is_delivered_aggressively": "Délivré de manière agressive", @@ -1748,17 +1748,17 @@ "advancements.unicopia.deter_phantom.title": "Ce qui vole autour", "advancements.unicopia.deter_phantom.description": "Montez là-haut et donnez à ces fantômes un goût de leur propre médicament", "advancements.unicopia.unicorn_route.title": "Corne de la Licorne", - "advancements.unicopia.unicorn_route.description": "Plongez dans le monde des arc-en-ciel et des éclaireurs", - "advancements.unicopia.books.title": "Livres!", + "advancements.unicopia.unicorn_route.description": "Plongez dans le monde des arcs-en-ciel et des éclaireurs", + "advancements.unicopia.books.title": "Livres !", "advancements.unicopia.books.description": "C'est MON livre de sorts et je vais le lire !", - "advancements.unicopia.books_books_books.title": "Livres! Livres! Livres!", + "advancements.unicopia.books_books_books.title": "Livres ! Livres ! Livres !", "advancements.unicopia.books_books_books.description": "Ayez un inventaire rempli de livres", "advancements.unicopia.tempted.title": "Tentative...", "advancements.unicopia.tempted.description": "Mettre sur l'amulette d'amulette de la licorne", "advancements.unicopia.hello_darkness_my_old_friend.title": "Bonjour les ténèbres...", "advancements.unicopia.hello_darkness_my_old_friend.description": "Plongez plus loin dans les puissances du côté sombre", "advancements.unicopia.a_falling_wizard.title": "Un sorcier en chute libre", - "advancements.unicopia.a_falling_wizard.description": "Une licorne a tenté de lancer un sort de vol infructueux", + "advancements.unicopia.a_falling_wizard.description": "Un(e) licorne a tenté d'effectuer sans succès un sort de vol", "advancements.unicopia.split_the_sea.title": "Qui êtes-vous? Moïse?", "advancements.unicopia.split_the_sea.description": "Utilisez la magie pour déplacer plus de 100 blocs d'eau en une seule fois", "advancements.unicopia.save_the_day.title": "Enregistrer le jour", @@ -1775,7 +1775,7 @@ "advancements.unicopia.love_is_power.description": "Bannir le Roi Sombra avec un cœur de cristal", "advancements.unicopia.hippogriff_route.title": "éclaboussure de Seaquestria", "advancements.unicopia.hippogriff_route.description": "Rejoignez le nid d'Hippogriff", - "advancements.unicopia.shoo_be_doo.title": "Shou Be Dou!", + "advancements.unicopia.shoo_be_doo.title": "Shou Be Dou !", "advancements.unicopia.shoo_be_doo.description": "Utilisez un collier de perles pour vous transformer en créature marine.", "advancements.unicopia.shoo_be_done.title": "Le Shoo est fait !", "advancements.unicopia.shoo_be_done.description": "Utilisez un collier de perles pour revenir à la normale", From 438d8b9f0ba286c9948c67bbcf50b11c6af9034c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 12 Oct 2024 15:01:22 +0100 Subject: [PATCH 079/110] New translations en_us.json (Chinese Traditional) --- src/main/resources/assets/unicopia/lang/zh_tw.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/unicopia/lang/zh_tw.json b/src/main/resources/assets/unicopia/lang/zh_tw.json index 454ab64a..e83a7287 100644 --- a/src/main/resources/assets/unicopia/lang/zh_tw.json +++ b/src/main/resources/assets/unicopia/lang/zh_tw.json @@ -531,10 +531,10 @@ "spell_attribute.unicopia.affects.blocks": "僅作用於方塊", "spell_attribute.unicopia.follows_target": "追蹤目標", "spell_attribute.unicopia.causes_levitation": "導致懸浮", - "spell_attribute.unicopia.permit_items": "Permits Items", + "spell_attribute.unicopia.permit_items": "允許物品", "spell_attribute.unicopia.permit_passive": "放行友好生物", "spell_attribute.unicopia.permit_hostile": "放行敵對生物", - "spell_attribute.unicopia.permit_player": "Permits Other Players", + "spell_attribute.unicopia.permit_player": " 允許其他玩家", "spell_attribute.unicopia.range": "效果作用範圍", "spell_attribute.unicopia.duration": "效果作用時長", "spell_attribute.unicopia.strength": "效果作用強度", From 93299feae6b0be01c1393070bdb9cb225d39a352 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 14 Oct 2024 18:45:49 +0100 Subject: [PATCH 080/110] Fixed the trick apple recipes # Conflicts: # src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/TrickCraftingRecipeJsonBuilder.java # src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java --- .../com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java b/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java index a92b956a..6ed7528c 100644 --- a/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java +++ b/src/main/java/com/minelittlepony/unicopia/recipe/ZapAppleRecipe.java @@ -8,6 +8,7 @@ import com.minelittlepony.unicopia.item.UItems; import net.minecraft.item.ItemStack; import net.minecraft.network.PacketByteBuf; import net.minecraft.recipe.Ingredient; +import net.minecraft.recipe.RecipeSerializer; import net.minecraft.recipe.ShapelessRecipe; import net.minecraft.recipe.book.CraftingRecipeCategory; import net.minecraft.util.Identifier; @@ -21,6 +22,11 @@ public class ZapAppleRecipe extends ShapelessRecipe { super(id, group, category, output, input); } + @Override + public RecipeSerializer getSerializer() { + return URecipes.ZAP_APPLE_SERIALIZER; + } + public static class Serializer extends ShapelessRecipe.Serializer { @Override public ShapelessRecipe read(Identifier identifier, JsonObject json) { From fd65e7db174862b0d2ee3295fd594af4d49a44b9 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 12 Oct 2024 21:23:59 +0100 Subject: [PATCH 081/110] Change early molting season advancements to regular tasks Closes #483 --- .../datagen/providers/UAdvancementsProvider.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java index 394516f9..4b1760fa 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java @@ -117,17 +117,17 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { p.child(UItems.LIGHTNING_JAR).hidden().frame(AdvancementFrame.CHALLENGE).apply(d -> applyLightningBugCriterions(d, RacePredicate.of(Set.of(Race.CHANGELING), Set.of()), 10, 90)).build(consumer, "lightning_bug"); p.child(UItems.LIGHTNING_JAR).hidden().frame(AdvancementFrame.CHALLENGE).apply(d -> applyLightningBugCriterions(d, RacePredicate.of(Set.of(), Set.of(Race.CHANGELING)), 10, 90)).build(consumer, "wonder_bolt"); }); - parent.child(UItems.PEGASUS_FEATHER).hidden().frame(AdvancementFrame.CHALLENGE).criterion("shed_feather", CustomEventCriterion.createFlying("shed_feather")).rewards(AdvancementRewards.Builder.experience(1)).build(consumer, "molting_season_1") + parent.child(UItems.PEGASUS_FEATHER).hidden().frame(AdvancementFrame.TASK).criterion("shed_feather", CustomEventCriterion.createFlying("shed_feather")).rewards(AdvancementRewards.Builder.experience(1)).build(consumer, "molting_season_1") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 2, 2)).build(consumer, "molting_season_2") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 4, 8)).build(consumer, "molting_season_3") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 8, 20)).build(consumer, "molting_season_4") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 16, 40)).build(consumer, "molting_season_5") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 32, 80)).build(consumer, "molting_season_6") .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 64, 200)).build(consumer, "molting_season_7") - .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 128, 500)).build(consumer, "molting_season_8") - .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 256, 1000)).build(consumer, "molting_season_9") - .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 512, 2280)).build(consumer, "molting_season_10") - .child(UItems.GOLDEN_FEATHER).apply(d -> applyShedFeatherCriterions(d, 1024, 4560)).build(consumer, "molting_season_11") + .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 128, 500)).frame(AdvancementFrame.CHALLENGE).build(consumer, "molting_season_8") + .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 256, 1000)).frame(AdvancementFrame.CHALLENGE).build(consumer, "molting_season_9") + .child(UItems.PEGASUS_FEATHER).apply(d -> applyShedFeatherCriterions(d, 512, 2280)).frame(AdvancementFrame.CHALLENGE).build(consumer, "molting_season_10") + .child(UItems.GOLDEN_FEATHER).apply(d -> applyShedFeatherCriterions(d, 1024, 4560)).frame(AdvancementFrame.CHALLENGE).build(consumer, "molting_season_11") .child(UItems.GOLDEN_FEATHER).apply(d -> applyShedFeatherCriterions(d, 2048, 10000)).frame(AdvancementFrame.GOAL).build(consumer, "dedicated_flier"); } From a43f5d2022b3cb2b19725beb2b1f3513b4fc19de Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 12 Oct 2024 21:44:46 +0100 Subject: [PATCH 082/110] Fix carver crash #490 --- .../unicopia/server/world/gen/CloudCarver.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java index 41736d0d..f92abb9a 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java @@ -167,7 +167,10 @@ public class CloudCarver extends CaveCarver { MutableBoolean replacedGrassy ) { if (super.carveAtPoint(context, config, chunk, posToBiome, mask, pos, tmp, aquiferSampler, replacedGrassy)) { - topWrittenPositions.remove(tmp.set(pos).move(Direction.DOWN).asLong()); + tmp.set(pos).move(Direction.DOWN); + if (!topWrittenPositions.isEmpty()) { + topWrittenPositions.remove(tmp.asLong()); + } topWrittenPositions.add(pos.asLong()); if (chunk.getBlockState(tmp).isOf(UBlocks.SOGGY_CLOUD)) { chunk.setBlockState(tmp, UBlocks.CLOUD.getDefaultState(), false); From 895a7bff604e09e02be96d936ac1c976dae8bf83 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sun, 13 Oct 2024 18:18:50 +0100 Subject: [PATCH 083/110] Change criterion check to an OR for tribe joins # Conflicts: # src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java --- .../unicopia/datagen/providers/UAdvancementsProvider.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java index 4b1760fa..42352276 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/UAdvancementsProvider.java @@ -67,6 +67,7 @@ public class UAdvancementsProvider extends FabricAdvancementProvider { for (Race r : extra) { builder.criterion("be_" + r.getId().getPath(), new RaceChangeCriterion.Conditions(LootContextPredicate.EMPTY, r)); } + builder.criteriaMerger(CriterionMerger.OR); } return builder.build(consumer, race.getId().getPath() + "_route"); From 652802b8444a0184b74510263e336e07f83a35f4 Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 14 Oct 2024 19:16:02 +0100 Subject: [PATCH 084/110] Fix #490 (again) --- .../server/world/gen/CloudCarver.java | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java index f92abb9a..b4406402 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java @@ -27,11 +27,6 @@ import net.minecraft.world.gen.chunk.AquiferSampler; import net.minecraft.world.gen.densityfunction.DensityFunction.NoisePos; public class CloudCarver extends CaveCarver { - - private Random random; - - private final LongSet topWrittenPositions = new LongOpenHashSet(); - public CloudCarver(Codec codec) { super(codec); } @@ -62,25 +57,13 @@ public class CloudCarver extends CaveCarver { ChunkPos chunkPos, CarvingMask carvingMask ) { - this.random = random; - boolean result = super.carve(context, config, chunk, function, random, new AquiferSampler() { - @Override - public BlockState apply(NoisePos pos, double density) { - BlockState state = sampler.apply(pos, density); - return state != null && state.isAir() ? UBlocks.CLOUD.getDefaultState() : state; - } - - @Override - public boolean needsFluidTick() { - return sampler.needsFluidTick(); - } - - }, chunkPos, carvingMask); + CloudCarverContext carverContext = new CloudCarverContext(sampler, random); + boolean result = super.carve(context, config, chunk, function, random, carverContext, chunkPos, carvingMask); BlockPos.Mutable mutable = new BlockPos.Mutable(); - topWrittenPositions.forEach(l -> { + carverContext.topWrittenPositions.forEach(l -> { processSurfaceBlocks(mutable.set(l), context, config, chunk, random); }); - topWrittenPositions.clear(); + carverContext.topWrittenPositions.clear(); return result; } @@ -99,17 +82,17 @@ public class CloudCarver extends CaveCarver { CarvingMask mask, Carver.SkipPredicate skipPredicate ) { - if (random == null) { + if (!(aquiferSampler instanceof CloudCarverContext c)) { return; } int maxY = context.getMinY() + context.getHeight(); - int bubbleCount = 10 + random.nextInt(12); + int bubbleCount = 10 + c.random.nextInt(12); for (int i = 0; i < bubbleCount; i++) { - double width = 1.5 * xScale + random.nextTriangular(3, 2); - double height = Math.min(width * yScale * (1 + random.nextFloat() * 2) + MathHelper.sin((float) (Math.PI / 2)) * xScale, maxY - y); - double bubbleX = x + (random.nextFloat() * 2 - 1) * width; - double bubbleZ = z + (random.nextFloat() * 2 - 1) * width; + double width = 1.5 * xScale +c.random.nextTriangular(3, 2); + double height = Math.min(width * yScale * (1 + c.random.nextFloat() * 2) + MathHelper.sin((float) (Math.PI / 2)) * xScale, maxY - y); + double bubbleX = x + (c.random.nextFloat() * 2 - 1) * width; + double bubbleZ = z + (c.random.nextFloat() * 2 - 1) * width; carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX + 1.0, y, bubbleZ, width, height, mask, skipPredicate); } } @@ -136,17 +119,17 @@ public class CloudCarver extends CaveCarver { CarvingMask mask, Carver.SkipPredicate skipPredicate ) { - if (random == null) { + if (!(aquiferSampler instanceof CloudCarverContext c)) { return; } int maxY = context.getMinY() + context.getHeight(); - int bubbleCount = 10 + random.nextInt(12); + int bubbleCount = 10 + c.random.nextInt(12); for (int i = 0; i < bubbleCount; i++) { - double width = /*1.5 + MathHelper.sin((float) (Math.PI / 2)) * xScale +*/ 1.5 * horizontalScale + random.nextInt(3) + w; - double height = width * (1 + random.nextFloat() * 2) * verticalScale * 0.2; - double bubbleX = x + (random.nextFloat() * 2 - 1) * width * 1.5; - double bubbleZ = z + (random.nextFloat() * 2 - 1) * width * 1.5; - double bubbleY = y + random.nextFloat() * height * 0.5; + double width = /*1.5 + MathHelper.sin((float) (Math.PI / 2)) * xScale +*/ 1.5 * horizontalScale + c.random.nextInt(3) + w; + double height = width * (1 + c.random.nextFloat() * 2) * verticalScale * 0.2; + double bubbleX = x + (c.random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleZ = z + (c.random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleY = y + c.random.nextFloat() * height * 0.5; if (bubbleY + height < maxY) { carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX, bubbleY, bubbleZ, width, height, mask, skipPredicate); } @@ -168,10 +151,12 @@ public class CloudCarver extends CaveCarver { ) { if (super.carveAtPoint(context, config, chunk, posToBiome, mask, pos, tmp, aquiferSampler, replacedGrassy)) { tmp.set(pos).move(Direction.DOWN); - if (!topWrittenPositions.isEmpty()) { - topWrittenPositions.remove(tmp.asLong()); + if (aquiferSampler instanceof CloudCarverContext c) { + if (!c.topWrittenPositions.isEmpty()) { + c.topWrittenPositions.remove(tmp.asLong()); + } + c.topWrittenPositions.add(pos.asLong()); } - topWrittenPositions.add(pos.asLong()); if (chunk.getBlockState(tmp).isOf(UBlocks.SOGGY_CLOUD)) { chunk.setBlockState(tmp, UBlocks.CLOUD.getDefaultState(), false); } @@ -185,4 +170,27 @@ public class CloudCarver extends CaveCarver { chunk.setBlockState(pos.move(Direction.DOWN), UBlocks.SOGGY_CLOUD.getDefaultState(), false); } } + + static class CloudCarverContext implements AquiferSampler { + + private final AquiferSampler sampler; + public final LongSet topWrittenPositions = new LongOpenHashSet(); + public final Random random; + + public CloudCarverContext(AquiferSampler sampler, Random random) { + this.sampler = sampler; + this.random = random; + } + + @Override + public BlockState apply(NoisePos pos, double density) { + BlockState state = sampler.apply(pos, density); + return state != null && state.isAir() ? UBlocks.CLOUD.getDefaultState() : state; + } + + @Override + public boolean needsFluidTick() { + return sampler.needsFluidTick(); + } + } } \ No newline at end of file From 36eb042ffae116f552fdc22fa506c9328bc5f4cd Mon Sep 17 00:00:00 2001 From: Sollace Date: Mon, 14 Oct 2024 19:16:02 +0100 Subject: [PATCH 085/110] Fix #490 (again) --- .../server/world/gen/CloudCarver.java | 82 ++++++++++--------- 1 file changed, 45 insertions(+), 37 deletions(-) diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java index f92abb9a..b4406402 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java @@ -27,11 +27,6 @@ import net.minecraft.world.gen.chunk.AquiferSampler; import net.minecraft.world.gen.densityfunction.DensityFunction.NoisePos; public class CloudCarver extends CaveCarver { - - private Random random; - - private final LongSet topWrittenPositions = new LongOpenHashSet(); - public CloudCarver(Codec codec) { super(codec); } @@ -62,25 +57,13 @@ public class CloudCarver extends CaveCarver { ChunkPos chunkPos, CarvingMask carvingMask ) { - this.random = random; - boolean result = super.carve(context, config, chunk, function, random, new AquiferSampler() { - @Override - public BlockState apply(NoisePos pos, double density) { - BlockState state = sampler.apply(pos, density); - return state != null && state.isAir() ? UBlocks.CLOUD.getDefaultState() : state; - } - - @Override - public boolean needsFluidTick() { - return sampler.needsFluidTick(); - } - - }, chunkPos, carvingMask); + CloudCarverContext carverContext = new CloudCarverContext(sampler, random); + boolean result = super.carve(context, config, chunk, function, random, carverContext, chunkPos, carvingMask); BlockPos.Mutable mutable = new BlockPos.Mutable(); - topWrittenPositions.forEach(l -> { + carverContext.topWrittenPositions.forEach(l -> { processSurfaceBlocks(mutable.set(l), context, config, chunk, random); }); - topWrittenPositions.clear(); + carverContext.topWrittenPositions.clear(); return result; } @@ -99,17 +82,17 @@ public class CloudCarver extends CaveCarver { CarvingMask mask, Carver.SkipPredicate skipPredicate ) { - if (random == null) { + if (!(aquiferSampler instanceof CloudCarverContext c)) { return; } int maxY = context.getMinY() + context.getHeight(); - int bubbleCount = 10 + random.nextInt(12); + int bubbleCount = 10 + c.random.nextInt(12); for (int i = 0; i < bubbleCount; i++) { - double width = 1.5 * xScale + random.nextTriangular(3, 2); - double height = Math.min(width * yScale * (1 + random.nextFloat() * 2) + MathHelper.sin((float) (Math.PI / 2)) * xScale, maxY - y); - double bubbleX = x + (random.nextFloat() * 2 - 1) * width; - double bubbleZ = z + (random.nextFloat() * 2 - 1) * width; + double width = 1.5 * xScale +c.random.nextTriangular(3, 2); + double height = Math.min(width * yScale * (1 + c.random.nextFloat() * 2) + MathHelper.sin((float) (Math.PI / 2)) * xScale, maxY - y); + double bubbleX = x + (c.random.nextFloat() * 2 - 1) * width; + double bubbleZ = z + (c.random.nextFloat() * 2 - 1) * width; carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX + 1.0, y, bubbleZ, width, height, mask, skipPredicate); } } @@ -136,17 +119,17 @@ public class CloudCarver extends CaveCarver { CarvingMask mask, Carver.SkipPredicate skipPredicate ) { - if (random == null) { + if (!(aquiferSampler instanceof CloudCarverContext c)) { return; } int maxY = context.getMinY() + context.getHeight(); - int bubbleCount = 10 + random.nextInt(12); + int bubbleCount = 10 + c.random.nextInt(12); for (int i = 0; i < bubbleCount; i++) { - double width = /*1.5 + MathHelper.sin((float) (Math.PI / 2)) * xScale +*/ 1.5 * horizontalScale + random.nextInt(3) + w; - double height = width * (1 + random.nextFloat() * 2) * verticalScale * 0.2; - double bubbleX = x + (random.nextFloat() * 2 - 1) * width * 1.5; - double bubbleZ = z + (random.nextFloat() * 2 - 1) * width * 1.5; - double bubbleY = y + random.nextFloat() * height * 0.5; + double width = /*1.5 + MathHelper.sin((float) (Math.PI / 2)) * xScale +*/ 1.5 * horizontalScale + c.random.nextInt(3) + w; + double height = width * (1 + c.random.nextFloat() * 2) * verticalScale * 0.2; + double bubbleX = x + (c.random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleZ = z + (c.random.nextFloat() * 2 - 1) * width * 1.5; + double bubbleY = y + c.random.nextFloat() * height * 0.5; if (bubbleY + height < maxY) { carveRegion(context, config, chunk, posToBiome, aquiferSampler, bubbleX, bubbleY, bubbleZ, width, height, mask, skipPredicate); } @@ -168,10 +151,12 @@ public class CloudCarver extends CaveCarver { ) { if (super.carveAtPoint(context, config, chunk, posToBiome, mask, pos, tmp, aquiferSampler, replacedGrassy)) { tmp.set(pos).move(Direction.DOWN); - if (!topWrittenPositions.isEmpty()) { - topWrittenPositions.remove(tmp.asLong()); + if (aquiferSampler instanceof CloudCarverContext c) { + if (!c.topWrittenPositions.isEmpty()) { + c.topWrittenPositions.remove(tmp.asLong()); + } + c.topWrittenPositions.add(pos.asLong()); } - topWrittenPositions.add(pos.asLong()); if (chunk.getBlockState(tmp).isOf(UBlocks.SOGGY_CLOUD)) { chunk.setBlockState(tmp, UBlocks.CLOUD.getDefaultState(), false); } @@ -185,4 +170,27 @@ public class CloudCarver extends CaveCarver { chunk.setBlockState(pos.move(Direction.DOWN), UBlocks.SOGGY_CLOUD.getDefaultState(), false); } } + + static class CloudCarverContext implements AquiferSampler { + + private final AquiferSampler sampler; + public final LongSet topWrittenPositions = new LongOpenHashSet(); + public final Random random; + + public CloudCarverContext(AquiferSampler sampler, Random random) { + this.sampler = sampler; + this.random = random; + } + + @Override + public BlockState apply(NoisePos pos, double density) { + BlockState state = sampler.apply(pos, density); + return state != null && state.isAir() ? UBlocks.CLOUD.getDefaultState() : state; + } + + @Override + public boolean needsFluidTick() { + return sampler.needsFluidTick(); + } + } } \ No newline at end of file From 762c1125a305b80cfb0fd0ad1f75493b7cbfcb15 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 15 Oct 2024 11:25:51 +0100 Subject: [PATCH 086/110] Fixed rocks popping off of farmland. Fixes #493 --- .../java/com/minelittlepony/unicopia/block/RockCropBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java b/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java index b89e89b5..844dcef2 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java @@ -64,7 +64,7 @@ public class RockCropBlock extends CropBlock { }; protected RockCropBlock(Settings settings) { - super(settings); + super(settings.notSolid()); } @Override From c9e8c8a3a98b12710f41068fe39be6b95fc16c05 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 15 Oct 2024 11:25:51 +0100 Subject: [PATCH 087/110] Fixed rocks popping off of farmland. Fixes #493 --- .../java/com/minelittlepony/unicopia/block/RockCropBlock.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java b/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java index efe80127..2a573123 100644 --- a/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java +++ b/src/main/java/com/minelittlepony/unicopia/block/RockCropBlock.java @@ -66,7 +66,7 @@ public class RockCropBlock extends CropBlock { }; protected RockCropBlock(Settings settings) { - super(settings); + super(settings.notSolid()); } @Override From e627a7471c5b3c3e605973f1cc8580eb9cbd6732 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Mon, 28 Oct 2024 17:59:05 +0000 Subject: [PATCH 088/110] New translations en_us.json (Russian) --- src/main/resources/assets/unicopia/lang/ru_ru.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/unicopia/lang/ru_ru.json b/src/main/resources/assets/unicopia/lang/ru_ru.json index f92a9a37..5e1b9c82 100644 --- a/src/main/resources/assets/unicopia/lang/ru_ru.json +++ b/src/main/resources/assets/unicopia/lang/ru_ru.json @@ -1488,6 +1488,8 @@ "death.attack.unicopia.bat_screech.self": "%1$ напугали себя до смерти", "death.attack.unicopia.bat_screech.player": "%2$s напугал %1$s", "death.attack.unicopia.bat_screech.item": "%1$s был напуган до смерти %2$s с помощью %3$s", + "death.attack.unicopia.rainboom": "%1$s's eardrums were shattered", + "death.attack.unicopia.rainboom.player": "%2$s's shattered %1$s's eardrums", "death.attack.unicopia.gravity_well_recoil": "%1$ превратился в спагетти", "death.attack.unicopia.gravity_well_recoil.player": "%1$s превращён в спагетти заклинанием, созданным %2$s", "death.attack.unicopia.gravity_well_recoil.item": "%1$s превращён в спагетти заклинанием, созданным %2$s с помощью %3$s", From 2e1702d23a25d6129c89e2acbe333c59710c3571 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Mon, 28 Oct 2024 17:59:07 +0000 Subject: [PATCH 089/110] New translations en_us.json (Chinese Simplified) --- src/main/resources/assets/unicopia/lang/zh_cn.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/unicopia/lang/zh_cn.json b/src/main/resources/assets/unicopia/lang/zh_cn.json index e1ba96f5..a667b7b6 100644 --- a/src/main/resources/assets/unicopia/lang/zh_cn.json +++ b/src/main/resources/assets/unicopia/lang/zh_cn.json @@ -1488,6 +1488,8 @@ "death.attack.unicopia.bat_screech.self": "%1$s 吓到了自己", "death.attack.unicopia.bat_screech.player": "%2$s 吓到了 %1$s", "death.attack.unicopia.bat_screech.item": "%1$s 被 %2$s 用 %3$s 吓到了", + "death.attack.unicopia.rainboom": "%1$s's eardrums were shattered", + "death.attack.unicopia.rainboom.player": "%2$s's shattered %1$s's eardrums", "death.attack.unicopia.gravity_well_recoil": "%1$s 被拉成了意大利面条", "death.attack.unicopia.gravity_well_recoil.player": "%1$s 被 %2$s 施放的魔法拉成了意大利面条", "death.attack.unicopia.gravity_well_recoil.item": "%1$s 被 %2$s 用 %3$s 施放的魔法拉成了意大利面条", From d3dd2e993da97826dd1b263eac0e58df601742d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Mon, 28 Oct 2024 17:59:09 +0000 Subject: [PATCH 090/110] New translations en_us.json (French) --- src/main/resources/assets/unicopia/lang/fr_fr.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/unicopia/lang/fr_fr.json b/src/main/resources/assets/unicopia/lang/fr_fr.json index e3432376..54e6a823 100644 --- a/src/main/resources/assets/unicopia/lang/fr_fr.json +++ b/src/main/resources/assets/unicopia/lang/fr_fr.json @@ -1488,6 +1488,8 @@ "death.attack.unicopia.bat_screech.self": "%1$s s'est effrayé", "death.attack.unicopia.bat_screech.player": "%2$s a effrayé %1$s", "death.attack.unicopia.bat_screech.item": "%1$s a été effrayé par %2$s en utilisant %3$s", + "death.attack.unicopia.rainboom": "%1$s's eardrums were shattered", + "death.attack.unicopia.rainboom.player": "%2$s's shattered %1$s's eardrums", "death.attack.unicopia.gravity_well_recoil": "%1$s turned into spaghetti", "death.attack.unicopia.gravity_well_recoil.player": "%1$s turned into spaghetti by a spell cast by %2$s", "death.attack.unicopia.gravity_well_recoil.item": "%1$s transformé en spaghetti par un sort lancé par %2$s en utilisant %3$s", From b998c433bce2234a5231379675b4e41daf6bf8e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Mon, 28 Oct 2024 17:59:11 +0000 Subject: [PATCH 091/110] New translations en_us.json (German) --- src/main/resources/assets/unicopia/lang/de_de.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/unicopia/lang/de_de.json b/src/main/resources/assets/unicopia/lang/de_de.json index b38fe9e6..118dcb84 100644 --- a/src/main/resources/assets/unicopia/lang/de_de.json +++ b/src/main/resources/assets/unicopia/lang/de_de.json @@ -1488,6 +1488,8 @@ "death.attack.unicopia.bat_screech.self": "%1$s hat sich geschockt", "death.attack.unicopia.bat_screech.player": "%2$s geschockt %1$s", "death.attack.unicopia.bat_screech.item": "%1$s wurde von %2$s mit %3$s erschreckt", + "death.attack.unicopia.rainboom": "%1$s's eardrums were shattered", + "death.attack.unicopia.rainboom.player": "%2$s's shattered %1$s's eardrums", "death.attack.unicopia.gravity_well_recoil": "%1$s wurde in Spaghetti verwandelt", "death.attack.unicopia.gravity_well_recoil.player": "%1$s wurde durch einen Zauberspruch von %2$s in Spaghetti umgewandelt", "death.attack.unicopia.gravity_well_recoil.item": "%1$s wurde durch einen Zauberspruch %2$s mit %3$s in Spaghetti umgewandelt", From 582f0cee54801597c5b07466f23998440a75b5bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Mon, 28 Oct 2024 17:59:12 +0000 Subject: [PATCH 092/110] New translations en_us.json (Chinese Traditional) --- src/main/resources/assets/unicopia/lang/zh_tw.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/unicopia/lang/zh_tw.json b/src/main/resources/assets/unicopia/lang/zh_tw.json index e83a7287..437d626a 100644 --- a/src/main/resources/assets/unicopia/lang/zh_tw.json +++ b/src/main/resources/assets/unicopia/lang/zh_tw.json @@ -1488,6 +1488,8 @@ "death.attack.unicopia.bat_screech.self": "%1$s把自己嚇死了", "death.attack.unicopia.bat_screech.player": "%2$s把%1$s嚇死了", "death.attack.unicopia.bat_screech.item": "%1$s被%2$s用%3$s嚇死了", + "death.attack.unicopia.rainboom": "%1$s's eardrums were shattered", + "death.attack.unicopia.rainboom.player": "%2$s's shattered %1$s's eardrums", "death.attack.unicopia.gravity_well_recoil": "%1$s變成了麪條", "death.attack.unicopia.gravity_well_recoil.player": "%1$s被%2$s的施咒變成了麪條", "death.attack.unicopia.gravity_well_recoil.item": "%1$s被%2$s的%3$s施咒變成了麪條", From 3f4d49df9f2a2395535b3b99c123ac0dd4d0b30f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Mon, 28 Oct 2024 17:59:13 +0000 Subject: [PATCH 093/110] New translations en_us.json (English, United Kingdom) --- src/main/resources/assets/unicopia/lang/en_gb.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/unicopia/lang/en_gb.json b/src/main/resources/assets/unicopia/lang/en_gb.json index 3c9ad5c2..b514dec6 100644 --- a/src/main/resources/assets/unicopia/lang/en_gb.json +++ b/src/main/resources/assets/unicopia/lang/en_gb.json @@ -1488,6 +1488,8 @@ "death.attack.unicopia.bat_screech.self": "%1$s spooked themselves", "death.attack.unicopia.bat_screech.player": "%2$s spooked %1$s", "death.attack.unicopia.bat_screech.item": "%1$s was spooked by %2$s using %3$s", + "death.attack.unicopia.rainboom": "%1$s's eardrums were shattered", + "death.attack.unicopia.rainboom.player": "%2$s's shattered %1$s's eardrums", "death.attack.unicopia.gravity_well_recoil": "%1$s turned into spaghetti", "death.attack.unicopia.gravity_well_recoil.player": "%1$s turned into spaghetti by a spell cast by %2$s", "death.attack.unicopia.gravity_well_recoil.item": "%1$s turned into spaghetti by a spell cast by %2$s using %3$s", From 53045b1af988482354bc4491eeb6d4e2a425d2dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Mon, 28 Oct 2024 17:59:15 +0000 Subject: [PATCH 094/110] New translations en_us.json (English (upside down)) --- src/main/resources/assets/unicopia/lang/en_ud.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/unicopia/lang/en_ud.json b/src/main/resources/assets/unicopia/lang/en_ud.json index 867ac202..10d6b149 100644 --- a/src/main/resources/assets/unicopia/lang/en_ud.json +++ b/src/main/resources/assets/unicopia/lang/en_ud.json @@ -1488,6 +1488,8 @@ "death.attack.unicopia.bat_screech.self": "sǝʌlǝsɯǝɥʇ pǝʞoods %1$s", "death.attack.unicopia.bat_screech.player": "%1$s pǝʞoods %2$s", "death.attack.unicopia.bat_screech.item": "%3$s ƃuᴉsn %2$s ʎq pǝʞoods sɐʍ %1$s", + "death.attack.unicopia.rainboom": "%1$s's eardrums were shattered", + "death.attack.unicopia.rainboom.player": "%2$s's shattered %1$s's eardrums", "death.attack.unicopia.gravity_well_recoil": "ᴉʇʇǝɥƃɐds oʇuᴉ pǝuɹnʇ %1$s", "death.attack.unicopia.gravity_well_recoil.player": "%2$s ʎq ʇsɐɔ llǝds ɐ ʎq ᴉʇʇǝɥƃɐds oʇuᴉ pǝuɹnʇ %1$s", "death.attack.unicopia.gravity_well_recoil.item": "%3$s ƃuᴉsn %2$s ʎq ʇsɐɔ llǝds ɐ ʎq ᴉʇʇǝɥƃɐds oʇuᴉ pǝuɹnʇ %1$s", From e596d6e4b4ad3d192f2b275aa4308a86a50eeee3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Tue, 29 Oct 2024 12:26:13 +0000 Subject: [PATCH 095/110] Update source file en_us.json --- src/main/resources/assets/unicopia/lang/en_us.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index a1dcbc02..ab336372 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -1637,6 +1637,8 @@ "death.attack.unicopia.bat_screech.self": "%1$s spooked themselves", "death.attack.unicopia.bat_screech.player": "%2$s spooked %1$s", "death.attack.unicopia.bat_screech.item": "%1$s was spooked by %2$s using %3$s", + "death.attack.unicopia.rainboom": "%1$s's eardrums were shattered", + "death.attack.unicopia.rainboom.player": "%2$s's shattered %1$s's eardrums", "death.attack.unicopia.gravity_well_recoil": "%1$s turned into spaghetti", "death.attack.unicopia.gravity_well_recoil.player": "%1$s turned into spaghetti by a spell cast by %2$s", "death.attack.unicopia.gravity_well_recoil.item": "%1$s turned into spaghetti by a spell cast by %2$s using %3$s", From ad7120cf6db45387ace6dacd52a0f5f8a4c2c5c5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Tue, 29 Oct 2024 12:26:16 +0000 Subject: [PATCH 096/110] New translations en_us.json (Chinese Simplified) --- src/main/resources/assets/unicopia/lang/zh_cn.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/resources/assets/unicopia/lang/zh_cn.json b/src/main/resources/assets/unicopia/lang/zh_cn.json index a667b7b6..f28f84f5 100644 --- a/src/main/resources/assets/unicopia/lang/zh_cn.json +++ b/src/main/resources/assets/unicopia/lang/zh_cn.json @@ -1488,8 +1488,8 @@ "death.attack.unicopia.bat_screech.self": "%1$s 吓到了自己", "death.attack.unicopia.bat_screech.player": "%2$s 吓到了 %1$s", "death.attack.unicopia.bat_screech.item": "%1$s 被 %2$s 用 %3$s 吓到了", - "death.attack.unicopia.rainboom": "%1$s's eardrums were shattered", - "death.attack.unicopia.rainboom.player": "%2$s's shattered %1$s's eardrums", + "death.attack.unicopia.rainboom": "%1$s的骨膜碎裂了", + "death.attack.unicopia.rainboom.player": "%2$s击碎了%1$s的骨膜", "death.attack.unicopia.gravity_well_recoil": "%1$s 被拉成了意大利面条", "death.attack.unicopia.gravity_well_recoil.player": "%1$s 被 %2$s 施放的魔法拉成了意大利面条", "death.attack.unicopia.gravity_well_recoil.item": "%1$s 被 %2$s 用 %3$s 施放的魔法拉成了意大利面条", From 695201db6e80d013ad71701c075dbb5c4bee068c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 2 Nov 2024 15:49:29 +0000 Subject: [PATCH 097/110] New translations en_us.json (Russian) --- src/main/resources/assets/unicopia/lang/ru_ru.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/unicopia/lang/ru_ru.json b/src/main/resources/assets/unicopia/lang/ru_ru.json index 5e1b9c82..a7655539 100644 --- a/src/main/resources/assets/unicopia/lang/ru_ru.json +++ b/src/main/resources/assets/unicopia/lang/ru_ru.json @@ -1,4 +1,5 @@ { + "resourcepack.unicopia.programmer_art": "Programmer Art (Unicopia)", "block.unicopia.bed.not_safe": "Вы не можете уснуть, пока рядом есть враги", "block.unicopia.bed.not_tired": "Сейчас вы не чувствуете усталости", "block.unicopia.bed.no_sleep.nocturnal": "Вы можете спать только днём или во время грозы", From 10212275e7e8d8a64c395a68a042646f62310b98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 2 Nov 2024 15:49:31 +0000 Subject: [PATCH 098/110] New translations en_us.json (Chinese Simplified) --- src/main/resources/assets/unicopia/lang/zh_cn.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/unicopia/lang/zh_cn.json b/src/main/resources/assets/unicopia/lang/zh_cn.json index f28f84f5..5b95f9a5 100644 --- a/src/main/resources/assets/unicopia/lang/zh_cn.json +++ b/src/main/resources/assets/unicopia/lang/zh_cn.json @@ -1,4 +1,5 @@ { + "resourcepack.unicopia.programmer_art": "Programmer Art (Unicopia)", "block.unicopia.bed.not_safe": "你现在不能休息,附近有敌人在游荡", "block.unicopia.bed.not_tired": "你现在并不觉得累", "block.unicopia.bed.no_sleep.nocturnal": "你只能在白天或雷暴中入眠", From 95ac65bc1ca38f529cd984da4e127cde408275ca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 2 Nov 2024 15:49:32 +0000 Subject: [PATCH 099/110] New translations en_us.json (French) --- src/main/resources/assets/unicopia/lang/fr_fr.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/unicopia/lang/fr_fr.json b/src/main/resources/assets/unicopia/lang/fr_fr.json index 54e6a823..2dfb7dc5 100644 --- a/src/main/resources/assets/unicopia/lang/fr_fr.json +++ b/src/main/resources/assets/unicopia/lang/fr_fr.json @@ -1,4 +1,5 @@ { + "resourcepack.unicopia.programmer_art": "Programmer Art (Unicopia)", "block.unicopia.bed.not_safe": "Vous ne pouvez pas vous reposer ici, les ennemis sont proches", "block.unicopia.bed.not_tired": "Tu ne te sens pas fatigué en ce moment", "block.unicopia.bed.no_sleep.nocturnal": "Vous ne pouvez dormir que dans la journée, ou dans les orages", From 04490470a9effbb0af74acf5f2a288e3c658a897 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 2 Nov 2024 15:49:33 +0000 Subject: [PATCH 100/110] New translations en_us.json (German) --- src/main/resources/assets/unicopia/lang/de_de.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/unicopia/lang/de_de.json b/src/main/resources/assets/unicopia/lang/de_de.json index 118dcb84..25545636 100644 --- a/src/main/resources/assets/unicopia/lang/de_de.json +++ b/src/main/resources/assets/unicopia/lang/de_de.json @@ -1,4 +1,5 @@ { + "resourcepack.unicopia.programmer_art": "Programmer Art (Unicopia)", "block.unicopia.bed.not_safe": "Du kannst jetzt nicht schlafen, es sind Monster in der Nähe", "block.unicopia.bed.not_tired": "Du bist noch nicht müde", "block.unicopia.bed.no_sleep.nocturnal": "Du kannst nur tagsüber oder bei Gewittern schlafen", From 35e232ae19c98f8ac0b7ef7d62127581eb1a7de5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 2 Nov 2024 15:49:35 +0000 Subject: [PATCH 101/110] New translations en_us.json (Chinese Traditional) --- src/main/resources/assets/unicopia/lang/zh_tw.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/unicopia/lang/zh_tw.json b/src/main/resources/assets/unicopia/lang/zh_tw.json index 437d626a..af688fc0 100644 --- a/src/main/resources/assets/unicopia/lang/zh_tw.json +++ b/src/main/resources/assets/unicopia/lang/zh_tw.json @@ -1,4 +1,5 @@ { + "resourcepack.unicopia.programmer_art": "Programmer Art (Unicopia)", "block.unicopia.bed.not_safe": "您不能在此休息,附近有敵人遊蕩", "block.unicopia.bed.not_tired": "您現在並不睏", "block.unicopia.bed.no_sleep.nocturnal": "您只能在白天或雷暴期間休息", From ef024e3b8f3ddcb108c5c584bcd8d390f791a399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 2 Nov 2024 15:49:36 +0000 Subject: [PATCH 102/110] New translations en_us.json (English, United Kingdom) --- src/main/resources/assets/unicopia/lang/en_gb.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/unicopia/lang/en_gb.json b/src/main/resources/assets/unicopia/lang/en_gb.json index b514dec6..64d7ac37 100644 --- a/src/main/resources/assets/unicopia/lang/en_gb.json +++ b/src/main/resources/assets/unicopia/lang/en_gb.json @@ -1,4 +1,5 @@ { + "resourcepack.unicopia.programmer_art": "Programmer Art (Unicopia)", "block.unicopia.bed.not_safe": "You may not rest here, there are enemies nearby", "block.unicopia.bed.not_tired": "You do not feel tired right now", "block.unicopia.bed.no_sleep.nocturnal": "You can only sleep in the day or during thunderstorms", From cc62bd1d830147483c297274a9abb553b98c15cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 2 Nov 2024 15:49:37 +0000 Subject: [PATCH 103/110] New translations en_us.json (English (upside down)) --- src/main/resources/assets/unicopia/lang/en_ud.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/unicopia/lang/en_ud.json b/src/main/resources/assets/unicopia/lang/en_ud.json index 10d6b149..05850a1b 100644 --- a/src/main/resources/assets/unicopia/lang/en_ud.json +++ b/src/main/resources/assets/unicopia/lang/en_ud.json @@ -1,4 +1,5 @@ { + "resourcepack.unicopia.programmer_art": "Programmer Art (Unicopia)", "block.unicopia.bed.not_safe": "ʎqɹɐǝu sǝᴉɯǝuǝ ǝɹɐ ǝɹǝɥʇ `ǝɹǝɥ ʇsǝɹ ʇou ʎɐɯ no⅄", "block.unicopia.bed.not_tired": "ʍou ʇɥƃᴉɹ pǝɹᴉʇ lǝǝɟ ʇou op no⅄", "block.unicopia.bed.no_sleep.nocturnal": "sɯɹoʇsɹǝpunɥʇ ƃuᴉɹnp ɹo ʎɐp ǝɥʇ uᴉ dǝǝls ʎluo uɐɔ no⅄", From f1ea3cacb6cc5bbcaeb57d7803f68205c6e15c20 Mon Sep 17 00:00:00 2001 From: Sollace Date: Sat, 2 Nov 2024 16:23:44 +0000 Subject: [PATCH 104/110] Bump blockus ref --- BlockusAddon | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/BlockusAddon b/BlockusAddon index 2e285380..48e9b657 160000 --- a/BlockusAddon +++ b/BlockusAddon @@ -1 +1 @@ -Subproject commit 2e285380cfa55da1b858c38833f05a56666c219f +Subproject commit 48e9b6578f028d5d71471c83796984ec0322f7ef From 1d3cfb9aa6bc1255f62f155db2d5775b08735909 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Sat, 2 Nov 2024 16:53:40 +0000 Subject: [PATCH 105/110] Update source file en_us.json --- src/main/resources/assets/unicopia/lang/en_us.json | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json index ab336372..45fd4625 100644 --- a/src/main/resources/assets/unicopia/lang/en_us.json +++ b/src/main/resources/assets/unicopia/lang/en_us.json @@ -1,4 +1,5 @@ { + "resourcepack.unicopia.programmer_art": "Programmer Art (Unicopia)", "block.unicopia.bed.not_safe": "You may not rest here, there are enemies nearby", "block.unicopia.bed.not_tired": "You do not feel tired right now", From 37a1d52f8cdb8f2874e33d0679af79500f945a22 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 10 Dec 2024 22:41:43 +0100 Subject: [PATCH 106/110] Remove empty mixin --- .../minelittlepony/unicopia/mixin/MixinEnchantment.java | 9 --------- src/main/resources/unicopia.mixin.json | 1 - 2 files changed, 10 deletions(-) delete mode 100644 src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java deleted file mode 100644 index ae883d4b..00000000 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantment.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.minelittlepony.unicopia.mixin; - -import org.spongepowered.asm.mixin.Mixin; -import net.minecraft.enchantment.Enchantment; - -@Mixin(Enchantment.class) -abstract class MixinEnchantment { - -} diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json index 9a63d0c6..27696822 100644 --- a/src/main/resources/unicopia.mixin.json +++ b/src/main/resources/unicopia.mixin.json @@ -19,7 +19,6 @@ "MixinComponentHolder", "MutableBlockLightStorage", "MixinDamageSource", - "MixinEnchantment", "MixinEnchantmentHelper", "MixinFallLocation", "MixinFishingBobberEntity", From 43fab8916bb71b829c13146b47998d0218295511 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 10 Dec 2024 23:10:36 +0100 Subject: [PATCH 107/110] Fix ##520 --- .../unicopia/mixin/MixinEnchantmentHelper.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java index 0dd1aacf..82a96870 100644 --- a/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java +++ b/src/main/java/com/minelittlepony/unicopia/mixin/MixinEnchantmentHelper.java @@ -8,12 +8,14 @@ import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import com.minelittlepony.unicopia.entity.player.Pony; +import com.minelittlepony.unicopia.item.enchantment.SimpleEnchantment; import net.minecraft.enchantment.Enchantment; import net.minecraft.enchantment.EnchantmentHelper; import net.minecraft.enchantment.EnchantmentLevelEntry; import net.minecraft.entity.LivingEntity; import net.minecraft.item.ItemStack; +import net.minecraft.item.Items; @Mixin(EnchantmentHelper.class) abstract class MixinEnchantmentHelper { @@ -30,6 +32,8 @@ abstract class MixinEnchantmentHelper { @Inject(method = "getPossibleEntries", at = @At("RETURN")) private static void onGetPossibleEntries(int power, ItemStack stack, boolean treasureAllowed, CallbackInfoReturnable> info) { - info.getReturnValue().removeIf(entry -> !entry.enchantment.isAcceptableItem(stack)); + if (!stack.isOf(Items.BOOK)) { + info.getReturnValue().removeIf(entry -> entry.enchantment instanceof SimpleEnchantment && !entry.enchantment.isAcceptableItem(stack)); + } } } From 7f767cadd473ef9a69e35082d0ac93569f254cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C2=ADSollace?= Date: Tue, 10 Dec 2024 23:25:56 +0100 Subject: [PATCH 108/110] Update bug_report.md --- .github/ISSUE_TEMPLATE/bug_report.md | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 50c1f090..0710d727 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -22,6 +22,7 @@ If applicable, add screenshots to help explain your problem. **Version Information:** - Minecraft Version: [e.g. 1.20.5] - Mine Little Pony Version: + - Unicopia Version: **Mod Loader:** - [ ] Fabric From f4766b08de273495de658a11c464365e5fa1babf Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 10 Dec 2024 23:43:43 +0100 Subject: [PATCH 109/110] Fix #519 --- .../java/com/minelittlepony/unicopia/server/world/Tree.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java b/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java index 54b57ac7..c2ee23ac 100644 --- a/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java +++ b/src/main/java/com/minelittlepony/unicopia/server/world/Tree.java @@ -132,7 +132,7 @@ public record Tree ( public Tree build() { RegistryKey> configuredFeatureId = RegistryKey.of(RegistryKeys.CONFIGURED_FEATURE, id); - Optional 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)); + Optional sapling = saplingId.map(id -> UBlocks.register(id, saplingConstructor.apply(new SaplingGenerator(id.toString(), Optional.empty(), Optional.of(configuredFeatureId), Optional.empty()), FabricBlockSettings.copy(Blocks.OAK_SAPLING)), ItemGroups.NATURAL)); Tree tree = new Tree(id, configParameters.apply(new TreeFeatureConfig.Builder( BlockStateProvider.of(logType), trunkPlacer, From b03d5e917e258199869abf7e73768ae08f1b5300 Mon Sep 17 00:00:00 2001 From: Sollace Date: Tue, 10 Dec 2024 23:56:47 +0100 Subject: [PATCH 110/110] Fixed farmer's delight cutting board recipes --- .../datagen/providers/recipe/CuttingBoardRecipeJsonBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/CuttingBoardRecipeJsonBuilder.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/CuttingBoardRecipeJsonBuilder.java index 71f12563..107c4c83 100644 --- a/src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/CuttingBoardRecipeJsonBuilder.java +++ b/src/main/java/com/minelittlepony/unicopia/datagen/providers/recipe/CuttingBoardRecipeJsonBuilder.java @@ -115,7 +115,7 @@ public class CuttingBoardRecipeJsonBuilder { public record Tool(Identifier type, TagKey tag) { static final Codec CODEC = RecordCodecBuilder.create(ii -> ii.group( Identifier.CODEC.fieldOf("type").forGetter(Tool::type), - TagKey.codec(RegistryKeys.ITEM).fieldOf("tag").forGetter(Tool::tag) + TagKey.unprefixedCodec(RegistryKeys.ITEM).fieldOf("tag").forGetter(Tool::tag) ).apply(ii, Tool::new)); } public record Result(Identifier item, int count) {