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)
diff --git a/build.gradle b/build.gradle
index cd55edfe..c49f6fde 100644
--- a/build.gradle
+++ b/build.gradle
@@ -77,9 +77,14 @@ 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}"
modCompileOnly "dev.onyxstudios.cardinal-components-api:cardinal-components-base:5.3.0"
modCompileOnly "dev.onyxstudios.cardinal-components-api:cardinal-components-entity:5.3.0"
+ } 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}"
@@ -98,7 +103,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 3ca5c348..040b73ac 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -30,8 +30,10 @@ org.gradle.daemon=false
nodium_version=1.1.0+1.20
# Testing
+ use_trinkets=1
use_pehkui=0
use_sodium=0
+ use_iris=1
farmers_delight_version=1.20.1-2.0.9
pehkui_version=3.7.8+1.14.4-1.20.2
diff --git a/lib/trinkets-dummy-3.8.0.jar b/lib/trinkets-dummy-3.8.0.jar
new file mode 100644
index 00000000..1e65318d
Binary files /dev/null and b/lib/trinkets-dummy-3.8.0.jar differ
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() {
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/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/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/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/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/ability/EarthPonyGrowAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/EarthPonyGrowAbility.java
index bb9b49e4..af04192f 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/ability/ScreechAbility.java b/src/main/java/com/minelittlepony/unicopia/ability/ScreechAbility.java
index 53c8b702..100905b9 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/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/ability/magic/MultiSpellSlot.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java
index e38184b7..50cb5902 100644
--- a/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java
+++ b/src/main/java/com/minelittlepony/unicopia/ability/magic/MultiSpellSlot.java
@@ -116,6 +116,9 @@ class MultiSpellSlot implements SpellSlots, NbtSerialisable {
if (s != null) {
s.setDead();
s.tickDying(owner);
+ if (s.isDead()) {
+ s.destroy(owner);
+ }
}
}
}
@@ -128,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/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) {
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/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/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 9eee830f..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) {
@@ -77,62 +74,60 @@ 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.get() == null) {
+ if (dimension.get().isEmpty()) {
+ setDimension(source.asWorld().getRegistryKey());
+ }
+ if (getPosition().isEmpty()) {
+ setPosition(source.asEntity().getPos());
+ }
+
+ CastSpellEntity entity = new CastSpellEntity(source.asWorld(), source, this);
+
+ 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.set(entity.getUuid());
+ } else {
+ if (getConnection(source) == null) {
+ setDead();
+ }
+ }
}
+
return !isDead();
}
@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());
}
}
@@ -140,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/DisplacementSpell.java b/src/main/java/com/minelittlepony/unicopia/ability/magic/spell/effect/DisplacementSpell.java
index 1afef18f..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
@@ -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() != null) {
+ projectile.getMaster().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/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/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;
}
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..e4d562c3 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();
}
@@ -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 fd526300..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;
@@ -30,10 +31,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;
@@ -105,10 +117,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
@@ -163,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 f4f5ba0b..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;
@@ -77,7 +78,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();
}
@@ -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 e0b495d1..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;
@@ -26,7 +28,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();
}
@@ -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/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..dcff5ff1 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);
@@ -86,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/block/cloud/NaturalCloudBlock.java b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java
index 2d7325dc..e950ba4b 100644
--- a/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java
+++ b/src/main/java/com/minelittlepony/unicopia/block/cloud/NaturalCloudBlock.java
@@ -25,10 +25,11 @@ public class NaturalCloudBlock extends PoreousCloudBlock {
public NaturalCloudBlock(Settings settings, boolean meltable,
@Nullable Supplier soggyBlock,
Supplier compactedBlock) {
- super(settings.nonOpaque(), meltable, soggyBlock);
+ super(settings, meltable, soggyBlock);
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 94ce19e8..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;
}
@@ -78,7 +92,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/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 0cdcab4b..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,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.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;
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));
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
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 1ad3f0a1..8fb1e403 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,10 +53,6 @@ public class UnicopiaClient implements ClientModInitializer {
return Pony.of(MinecraftClient.getInstance().player);
}
- @Nullable
- private Float originalRainGradient;
- private final Lerp rainGradient = new Lerp(0);
-
public final Lerp tangentalSkyAngle = new Lerp(0, true);
public final Lerp skyAngle = new Lerp(0, true);
@@ -106,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;
}
@@ -157,38 +147,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/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/TribeConfirmationScreen.java b/src/main/java/com/minelittlepony/unicopia/client/gui/TribeConfirmationScreen.java
index 50967105..d329b50b 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();
}
@@ -119,30 +121,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/java/com/minelittlepony/unicopia/client/gui/UHud.java b/src/main/java/com/minelittlepony/unicopia/client/gui/UHud.java
index 1dd0ae28..687bcffb 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
@@ -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();
@@ -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/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java
index 399a8cea..9259e775 100644
--- a/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java
+++ b/src/main/java/com/minelittlepony/unicopia/client/minelittlepony/Main.java
@@ -116,7 +116,9 @@ public class Main extends MineLPDelegate implements ClientModInitializer {
@Override
public float getPonyHeight(Entity entity) {
- return super.getPonyHeight(entity) * com.minelittlepony.api.pony.Pony.getManager().getPony(entity).map(pony -> pony.metadata().size().scaleFactor() + 0.1F).orElse(1F);
+ return super.getPonyHeight(entity) * com.minelittlepony.api.pony.Pony.getManager().getPony(entity)
+ .map(pony -> pony.race().isHuman() ? 1 : pony.metadata().size().scaleFactor() + 0.1F)
+ .orElse(1F);
}
private static Race toUnicopiaRace(com.minelittlepony.api.pony.meta.Race race) {
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);
}
}
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/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 {
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();
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);
}
}
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/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) {
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 b75fd8e8..31e41416 100644
--- a/src/main/java/com/minelittlepony/unicopia/command/ManaCommand.java
+++ b/src/main/java/com/minelittlepony/unicopia/command/ManaCommand.java
@@ -24,7 +24,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 -> {
@@ -48,7 +48,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);
}
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/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/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/UDamageTypeProvider.java b/src/main/java/com/minelittlepony/unicopia/datagen/providers/tag/UDamageTypeProvider.java
index a257ccb4..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,
@@ -35,9 +40,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,
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..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
@@ -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() {
@@ -348,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);
diff --git a/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java b/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java
index 8c2ba874..11000da1 100644
--- a/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java
+++ b/src/main/java/com/minelittlepony/unicopia/entity/AttributeContainer.java
@@ -26,7 +26,7 @@ public interface AttributeContainer {
EntityAttributeModifier modifier = instance.getModifier(id);
if (!MathHelper.approximatelyEquals(desiredValue, modifier == null ? 0 : modifier.getValue())) {
- instance.tryRemoveModifier(id);
+ instance.removeModifier(id);
if (desiredValue != 0) {
if (permanent) {
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()) {
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 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/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
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 6c272cca..7f9a1011 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() {
@@ -392,4 +396,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/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()) {
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..ed9c57c4 100644
--- a/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java
+++ b/src/main/java/com/minelittlepony/unicopia/entity/effect/UPotions.java
@@ -20,11 +20,11 @@ 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_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);
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) {
diff --git a/src/main/java/com/minelittlepony/unicopia/entity/player/Acrobatics.java b/src/main/java/com/minelittlepony/unicopia/entity/player/Acrobatics.java
index e86b61c8..8e529828 100644
--- a/src/main/java/com/minelittlepony/unicopia/entity/player/Acrobatics.java
+++ b/src/main/java/com/minelittlepony/unicopia/entity/player/Acrobatics.java
@@ -58,6 +58,8 @@ public class Acrobatics implements Tickable, NbtSerialisable {
public void tick() {
BlockPos climbingPos = entity.getClimbingPos().orElse(null);
+ BlockPos hangingPos = pony.getPhysics().getHeadPosition();
+
if (!pony.getPhysics().isFlying() && !entity.getAbilities().flying
&& climbingPos != null
&& pony.getObservedSpecies() == Race.CHANGELING
@@ -68,7 +70,8 @@ public class Acrobatics implements Tickable, NbtSerialisable {
}
distanceClimbed += Math.abs(pony.getMotion().getClientVelocity().y);
- BlockPos hangingPos = entity.getBlockPos().up();
+
+
boolean canhangHere = canHangAt(hangingPos);
if (distanceClimbed > 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();
}
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..568e1331 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);
}
}
@@ -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()) {
@@ -463,7 +464,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);
@@ -530,7 +531,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) {
@@ -689,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;
@@ -829,8 +830,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 +863,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 cfe236a9..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);
@@ -597,7 +602,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;
}
}
@@ -703,7 +708,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);
}
}
@@ -807,7 +812,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;
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);
}
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/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/SpellbookItem.java b/src/main/java/com/minelittlepony/unicopia/item/SpellbookItem.java
index 1fefc4e8..a853ffa3 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.state().get(DispenserBlock.FACING);
- BlockPos pos = source.pos().offset(facing);
+ public TypedActionResult dispenseStack(BlockPointer pointer, ItemStack stack) {
+ Direction facing = pointer.state().get(DispenserBlock.FACING);
+ Position pos = DispenserBlock.getOutputLocation(pointer);
float yaw = facing.getOpposite().asRotation();
- placeBook(stack, source.world(), pos.getX(), pos.getY(), pos.getZ(), yaw, null);
- stack.decrement(1);
+ if (placeBook(stack, pointer.world(), 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;
}
}
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);
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/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/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/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",
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/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/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);
+ }
}
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/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));
}
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;
}
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/UWorldGen.java b/src/main/java/com/minelittlepony/unicopia/server/world/UWorldGen.java
index c7c781a6..2c8d1903 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,10 @@ 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.CloudCarver;
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 +26,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;
@@ -35,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;
@@ -120,6 +127,12 @@ 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);
+
+ 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) {
@@ -136,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/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 ac2d4e84..cc77d9ea 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(Heightmap.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;
}
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 6ab36008..a094a5aa 100644
--- a/src/main/java/com/minelittlepony/unicopia/server/world/WorldOverlay.java
+++ b/src/main/java/com/minelittlepony/unicopia/server/world/WorldOverlay.java
@@ -98,7 +98,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<>());
+ }
+}
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/CloudCarver.java b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java
new file mode 100644
index 00000000..41736d0d
--- /dev/null
+++ b/src/main/java/com/minelittlepony/unicopia/server/world/gen/CloudCarver.java
@@ -0,0 +1,185 @@
+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;
+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;
+
+ private final LongSet topWrittenPositions = new LongOpenHashSet();
+
+ 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;
+ 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);
+ BlockPos.Mutable mutable = new BlockPos.Mutable();
+ topWrittenPositions.forEach(l -> {
+ processSurfaceBlocks(mutable.set(l), context, config, chunk, random);
+ });
+ topWrittenPositions.clear();
+ return result;
+ }
+
+ @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);
+ }
+
+ @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
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/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);
diff --git a/src/main/resources/assets/unicopia/lang/en_us.json b/src/main/resources/assets/unicopia/lang/en_us.json
index 3d8903f2..df90e36b 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": "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",
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 b030c4a7..bfe6574f 100644
Binary files a/src/main/resources/assets/unicopia/textures/block/soggy_cloud_side.png and b/src/main/resources/assets/unicopia/textures/block/soggy_cloud_side.png differ
diff --git a/src/main/resources/assets/unicopia/textures/block/soggy_cloud_slab_side.png b/src/main/resources/assets/unicopia/textures/block/soggy_cloud_slab_side.png
index d0c064b0..8817ab38 100644
Binary files a/src/main/resources/assets/unicopia/textures/block/soggy_cloud_slab_side.png and b/src/main/resources/assets/unicopia/textures/block/soggy_cloud_slab_side.png differ
diff --git a/src/main/resources/assets/unicopia/textures/block/soggy_cloud_top.png b/src/main/resources/assets/unicopia/textures/block/soggy_cloud_top.png
index bbc1fdd9..ed6d470c 100644
Binary files a/src/main/resources/assets/unicopia/textures/block/soggy_cloud_top.png and b/src/main/resources/assets/unicopia/textures/block/soggy_cloud_top.png differ
diff --git a/src/main/resources/assets/unicopia/textures/gui/hud.png b/src/main/resources/assets/unicopia/textures/gui/hud.png
index 7070f5ad..6fcab1f6 100644
Binary files a/src/main/resources/assets/unicopia/textures/gui/hud.png and b/src/main/resources/assets/unicopia/textures/gui/hud.png differ
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 00000000..2a6cd5e5
Binary files /dev/null and b/src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_lower.nbt differ
diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_upper.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_upper.nbt
new file mode 100644
index 00000000..c2eb01d0
Binary files /dev/null and b/src/main/resources/data/unicopia/structures/changeling_hive/entrance_large_upper.nbt differ
diff --git a/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/empty.nbt b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/empty.nbt
new file mode 100644
index 00000000..106da760
Binary files /dev/null and b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/empty.nbt differ
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 00000000..86e553a7
Binary files /dev/null and b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_1.nbt differ
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 00000000..185d053b
Binary files /dev/null and b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_2.nbt differ
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 00000000..53574e14
Binary files /dev/null and b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/slime_3.nbt differ
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 00000000..c3932214
Binary files /dev/null and b/src/main/resources/data/unicopia/structures/changeling_hive/floor_decoration/spikes.nbt differ
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 00000000..bd44b266
Binary files /dev/null and b/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/empty.nbt differ
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 00000000..521802b8
Binary files /dev/null and b/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/slime.nbt differ
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 00000000..7a388fab
Binary files /dev/null and b/src/main/resources/data/unicopia/structures/changeling_hive/roof_decoration/spikes.nbt differ
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/data/unicopia/worldgen/processor_list/changeling_hive_decay.json b/src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_decay.json
index 63441ea5..4e9c23c6 100644
--- a/src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_decay.json
+++ b/src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_decay.json
@@ -13,10 +13,23 @@
},
"output_state": {
"name": "unicopia:hive",
- "Name": "unicopia:hive",
- "properties": []
+ "Name": "unicopia:hive"
}
}
]
+ },
+ {
+ "processor_type": "unicopia:cave_carving"
+ },
+ {
+ "processor_type": "unicopia:surface_growth",
+ "input_predicate": {
+ "predicate_type": "block_match",
+ "block": "unicopia:chitin"
+ },
+ "output_state": {
+ "name": "unicopia:surface_chitin",
+ "Name": "unicopia:surface_chitin"
+ }
}
]
\ No newline at end of file
diff --git a/src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_entrance_decay.json b/src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_entrance_decay.json
new file mode 100644
index 00000000..0ab08c0b
--- /dev/null
+++ b/src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_entrance_decay.json
@@ -0,0 +1,32 @@
+[
+ {
+ "processor_type": "minecraft:rule",
+ "rules": [
+ {
+ "location_predicate": {
+ "predicate_type": "always_true"
+ },
+ "input_predicate": {
+ "predicate_type": "random_block_match",
+ "block": "unicopia:chitin",
+ "probability": 0.2
+ },
+ "output_state": {
+ "name": "unicopia:hive",
+ "Name": "unicopia:hive"
+ }
+ }
+ ]
+ },
+ {
+ "processor_type": "unicopia:surface_growth",
+ "input_predicate": {
+ "predicate_type": "block_match",
+ "block": "unicopia:chitin"
+ },
+ "output_state": {
+ "name": "unicopia:surface_chitin",
+ "Name": "unicopia:surface_chitin"
+ }
+ }
+]
\ No newline at end of file
diff --git a/src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_surfacing.json b/src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_surfacing.json
new file mode 100644
index 00000000..91d90a09
--- /dev/null
+++ b/src/main/resources/data/unicopia/worldgen/processor_list/changeling_hive_surfacing.json
@@ -0,0 +1,13 @@
+[
+ {
+ "processor_type": "unicopia:surface_growth",
+ "input_predicate": {
+ "predicate_type": "block_match",
+ "block": "unicopia:chitin"
+ },
+ "output_state": {
+ "name": "unicopia:surface_chitin",
+ "Name": "unicopia:surface_chitin"
+ }
+ }
+]
\ No newline at end of file
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..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
@@ -18,10 +18,10 @@
}
},
"start_height": {
- "absolute": -7
+ "absolute": -6
},
"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
diff --git a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/chamber_decors.json b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/chamber_decors.json
index beb46991..68d93295 100644
--- a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/chamber_decors.json
+++ b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/chamber_decors.json
@@ -4,9 +4,7 @@
"element": {
"element_type": "minecraft:single_pool_element",
"location": "unicopia:changeling_hive/chamber_decoration/nothing",
- "processors": {
- "processors": []
- },
+ "processors": "unicopia:changeling_hive_surfacing",
"projection": "rigid"
},
"weight": 7
@@ -24,9 +22,7 @@
"element": {
"element_type": "minecraft:single_pool_element",
"location": "unicopia:changeling_hive/chamber_decoration/spiders",
- "processors": {
- "processors": []
- },
+ "processors": "unicopia:changeling_hive_surfacing",
"projection": "rigid"
},
"weight": 4
@@ -35,9 +31,7 @@
"element": {
"element_type": "minecraft:single_pool_element",
"location": "unicopia:changeling_hive/chamber_decoration/spiked",
- "processors": {
- "processors": []
- },
+ "processors": "unicopia:changeling_hive_surfacing",
"projection": "rigid"
},
"weight": 2
@@ -46,9 +40,7 @@
"element": {
"element_type": "minecraft:single_pool_element",
"location": "unicopia:changeling_hive/chamber_decoration/slime",
- "processors": {
- "processors": []
- },
+ "processors": "unicopia:changeling_hive_surfacing",
"projection": "rigid"
},
"weight": 2
diff --git a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/floor_additions.json b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/floor_additions.json
new file mode 100644
index 00000000..b4619725
--- /dev/null
+++ b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/floor_additions.json
@@ -0,0 +1,50 @@
+{
+ "elements": [
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/floor_decoration/empty",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 6
+ },
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/floor_decoration/slime_1",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 1
+ },
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/floor_decoration/slime_2",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 1
+ },
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/floor_decoration/slime_3",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 1
+ },
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/floor_decoration/spikes",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 3
+ }
+ ],
+ "fallback": "unicopia:changeling_hive/floor_additions_termination"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/floor_additions_termination.json b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/floor_additions_termination.json
new file mode 100644
index 00000000..a75d7346
--- /dev/null
+++ b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/floor_additions_termination.json
@@ -0,0 +1,14 @@
+{
+ "elements": [
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/floor_decoration/empty",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 1
+ }
+ ],
+ "fallback": "minecraft:empty"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/main_entrance_shafts.json b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/main_entrance_shafts.json
new file mode 100644
index 00000000..872201a0
--- /dev/null
+++ b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/main_entrance_shafts.json
@@ -0,0 +1,14 @@
+{
+ "elements": [
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/entrance_large_lower",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 6
+ }
+ ],
+ "fallback": "minecraft:empty"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/pit_decors.json b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/pit_decors.json
index f5380f91..660a7749 100644
--- a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/pit_decors.json
+++ b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/pit_decors.json
@@ -4,9 +4,7 @@
"element": {
"element_type": "minecraft:single_pool_element",
"location": "unicopia:changeling_hive/pit_decoration/eggs",
- "processors": {
- "processors": []
- },
+ "processors": "unicopia:changeling_hive_surfacing",
"projection": "rigid"
},
"weight": 1
@@ -15,9 +13,7 @@
"element": {
"element_type": "minecraft:single_pool_element",
"location": "unicopia:changeling_hive/pit_decoration/lava",
- "processors": {
- "processors": []
- },
+ "processors": "unicopia:changeling_hive_surfacing",
"projection": "rigid"
},
"weight": 1
@@ -35,9 +31,7 @@
"element": {
"element_type": "minecraft:single_pool_element",
"location": "unicopia:changeling_hive/pit_decoration/spiders",
- "processors": {
- "processors": []
- },
+ "processors": "unicopia:changeling_hive_surfacing",
"projection": "rigid"
},
"weight": 1
@@ -46,9 +40,7 @@
"element": {
"element_type": "minecraft:single_pool_element",
"location": "unicopia:changeling_hive/pit_decoration/spikes",
- "processors": {
- "processors": []
- },
+ "processors": "unicopia:changeling_hive_surfacing",
"projection": "rigid"
},
"weight": 1
@@ -57,9 +49,7 @@
"element": {
"element_type": "minecraft:single_pool_element",
"location": "unicopia:changeling_hive/pit_decoration/bulb",
- "processors": {
- "processors": []
- },
+ "processors": "unicopia:changeling_hive_surfacing",
"projection": "rigid"
},
"weight": 1
diff --git a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/roof_additions.json b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/roof_additions.json
new file mode 100644
index 00000000..0dff505a
--- /dev/null
+++ b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/roof_additions.json
@@ -0,0 +1,32 @@
+{
+ "elements": [
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/roof_decoration/empty",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 6
+ },
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/roof_decoration/slime",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 1
+ },
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/roof_decoration/spikes",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 3
+ }
+ ],
+ "fallback": "unicopia:changeling_hive/roof_additions_termination"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/roof_additions_termination.json b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/roof_additions_termination.json
new file mode 100644
index 00000000..307bb99b
--- /dev/null
+++ b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/roof_additions_termination.json
@@ -0,0 +1,14 @@
+{
+ "elements": [
+ {
+ "element": {
+ "element_type": "minecraft:single_pool_element",
+ "location": "unicopia:changeling_hive/roof_decoration/empty",
+ "processors": [],
+ "projection": "rigid"
+ },
+ "weight": 1
+ }
+ ],
+ "fallback": "minecraft:empty"
+}
\ No newline at end of file
diff --git a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/start.json b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/start.json
index 2b17e07a..5bfb0c50 100644
--- a/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/start.json
+++ b/src/main/resources/data/unicopia/worldgen/template_pool/changeling_hive/start.json
@@ -3,26 +3,8 @@
{
"element": {
"element_type": "minecraft:single_pool_element",
- "location": "unicopia:changeling_hive/entrance",
- "processors": "unicopia:changeling_hive_decay",
- "projection": "rigid"
- },
- "weight": 3
- },
- {
- "element": {
- "element_type": "minecraft:single_pool_element",
- "location": "unicopia:changeling_hive/spiked/entrance",
- "processors": "unicopia:changeling_hive_decay",
- "projection": "rigid"
- },
- "weight": 3
- },
- {
- "element": {
- "element_type": "minecraft:single_pool_element",
- "location": "unicopia:changeling_hive/slimey/entrance",
- "processors": "unicopia:changeling_hive_decay",
+ "location": "unicopia:changeling_hive/entrance_large_upper",
+ "processors": "unicopia:changeling_hive_entrance_decay",
"projection": "rigid"
},
"weight": 1
diff --git a/src/main/resources/unicopia.mixin.json b/src/main/resources/unicopia.mixin.json
index 17bd2121..533483c0 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",
@@ -27,6 +28,7 @@
"MixinFallingBlockEntity",
"MixinFlowableFluid",
"MixinGuardianTargetPredicate",
+ "MixinHeightmap",
"MixinItem",
"MixinItemEntity",
"MixinItemStack",
@@ -52,6 +54,7 @@
"MixinWorld",
"PointOfInterestTypesAccessor",
"server.MixinEntityTrackerEntry",
+ "server.MixinPathNodeMaker",
"server.MixinPlayerManager",
"server.MixinServerPlayerEntity",
"server.MixinServerPlayNetworkHandler",