mirror of
https://github.com/Sollace/Unicopia.git
synced 2024-11-23 13:37:58 +01:00
Merge branch '1.20.1' into 1.20.2
This commit is contained in:
commit
e317df4bf9
147 changed files with 1814 additions and 518 deletions
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
38
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
|
@ -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.
|
||||
|
||||
<details>
|
||||
```
|
||||
**Paste logs here**
|
||||
```
|
||||
</details>
|
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
26
.github/ISSUE_TEMPLATE/feature_request.md
vendored
Normal file
|
@ -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)
|
12
build.gradle
12
build.gradle
|
@ -77,9 +77,14 @@ dependencies {
|
|||
include "com.sollace:Romanizer:Romanizer:1.0.2"
|
||||
|
||||
modCompileOnly "com.terraformersmc:modmenu:${project.modmenu_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') {
|
||||
|
|
|
@ -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
|
||||
|
|
BIN
lib/trinkets-dummy-3.8.0.jar
Normal file
BIN
lib/trinkets-dummy-3.8.0.jar
Normal file
Binary file not shown.
|
@ -22,7 +22,7 @@ public interface EquineContext {
|
|||
}
|
||||
|
||||
default boolean collidesWithClouds() {
|
||||
return getCompositeRace().canInteractWithClouds();
|
||||
return getCompositeRace().canInteractWithClouds() || getCloudWalkingStrength() >= 1;
|
||||
}
|
||||
|
||||
default boolean hasFeatherTouch() {
|
||||
|
|
|
@ -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> 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<Pony> getClientPony() {
|
||||
|
|
|
@ -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)
|
||||
);
|
||||
|
|
|
@ -46,6 +46,7 @@ public interface UConventionalTags {
|
|||
TagKey<Item> FRUITS = item("fruits");
|
||||
TagKey<Item> WORMS = item("worms");
|
||||
TagKey<Item> ROCKS = item("rocks");
|
||||
TagKey<Item> GEMS = item("gems");
|
||||
|
||||
TagKey<Item> RAW_INSECT = item("raw_insect");
|
||||
TagKey<Item> COOKED_INSECT = item("cooked_insect");
|
||||
|
|
|
@ -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());
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@ public class BatPonyHangAbility implements Ability<Multi> {
|
|||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
|
|
@ -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,8 +71,10 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
|||
for (BlockPos pos : BlockPos.iterate(
|
||||
data.pos().add(-2, -2, -2),
|
||||
data.pos().add( 2, 2, 2))) {
|
||||
if (player.canModifyAt(pos, ModificationType.PHYSICAL)) {
|
||||
count += applySingle(player, player.asWorld(), player.asWorld().getBlockState(pos), pos);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
count = 1;
|
||||
}
|
||||
|
|
|
@ -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<Pos> {
|
|||
}
|
||||
|
||||
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<Pos> {
|
|||
|
||||
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) -> {
|
||||
if (iplayer.canModifyAt(p, ModificationType.PHYSICAL)) {
|
||||
Block.dropStacks(w.getBlockState(p), w, p);
|
||||
w.setBlockState(p, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Hit> {
|
|||
|
||||
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<Hit> {
|
|||
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<Hit> {
|
|||
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) {
|
||||
|
|
|
@ -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<Numeric> {
|
|||
|
||||
@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)
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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<Hit> {
|
||||
|
||||
|
@ -27,7 +28,7 @@ public class ToggleFlightAbility implements Ability<Hit> {
|
|||
@Nullable
|
||||
@Override
|
||||
public Optional<Hit> 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<Hit> {
|
|||
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);
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Float> RANGE = SpellAttribute.create(SpellAttributeType.RANGE, AttributeFormat.REGULAR, AttributeFormat.PERCENTAGE, Trait.POWER, power -> Math.max(0, 4 + power));
|
||||
protected static final SpellAttribute<Float> 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) {
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -26,11 +26,18 @@ public class DispersableDisguiseSpell extends AbstractDisguiseSpell implements I
|
|||
private final DataTracker.Entry<Boolean> 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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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<RegistryKey<World>> dimension = Optional.empty();
|
||||
private Optional<Vec3d> position = Optional.empty();
|
||||
private Optional<Vec3d> orientation = Optional.empty();
|
||||
private final DataTracker.Entry<UUID> placedEntityId = dataTracker.startTracking(TrackableDataType.UUID, null);
|
||||
private final DataTracker.Entry<Optional<RegistryKey<World>>> dimension = dataTracker.startTracking(TrackableDataType.ofRegistryKey(), Optional.empty());
|
||||
private final DataTracker.Entry<Optional<Vec3d>> position = dataTracker.startTracking(TrackableDataType.OPTIONAL_VECTOR, Optional.empty());
|
||||
private final DataTracker.Entry<Optional<Vec3d>> 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<Vec3d> getPosition() {
|
||||
return position;
|
||||
return position.get();
|
||||
}
|
||||
|
||||
public void setDimension(RegistryKey<World> 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) {
|
||||
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<World> 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 {
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -25,11 +25,6 @@ public final class SpellReference<T extends Spell> 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) {
|
||||
|
|
|
@ -20,7 +20,6 @@ public abstract class AbstractSpell implements Spell {
|
|||
|
||||
private final DataTracker.Entry<Boolean> dead = dataTracker.startTracking(TrackableDataType.BOOLEAN, false);
|
||||
private final DataTracker.Entry<Boolean> dying = dataTracker.startTracking(TrackableDataType.BOOLEAN, false);
|
||||
private boolean dirty;
|
||||
private final DataTracker.Entry<Boolean> 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");
|
||||
}
|
||||
|
|
|
@ -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<Entity> target = new EntityReference<>();
|
||||
private final EntityReference<Entity> 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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Float> radius;
|
||||
private DataTracker.Entry<Integer> struggles;
|
||||
private DataTracker.Entry<Float> radius = dataTracker.startTracking(TrackableDataType.FLOAT, 0F);
|
||||
private DataTracker.Entry<Integer> 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
|
||||
|
|
|
@ -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<Float> 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<Entity> target = new EntityReference<>();
|
||||
private final EntityReference<Entity> 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 (!originator.isClient()) {
|
||||
target.ifPresent(originator.asWorld(), target -> {
|
||||
target.setGlowing(true);
|
||||
if (ticks == 0) {
|
||||
target.ifPresent(originator.asWorld(), target -> apply(originator, target));
|
||||
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"));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Entity> target = new EntityReference<>();
|
||||
private final EntityReference<Entity> target = dataTracker.startTracking(new EntityReference<>());
|
||||
|
||||
protected FireBoltSpell(CustomisedSpellType<?> type) {
|
||||
super(type);
|
||||
|
|
|
@ -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<EntityReference<FairyEntity>> lights = new ArrayList<>();
|
||||
|
||||
protected LightSpell(CustomisedSpellType<?> type) {
|
||||
super(type);
|
||||
timer = new Timer(TIME.get(getTraits()));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -46,7 +46,7 @@ public class PortalSpell extends AbstractSpell implements PlacementControlSpell.
|
|||
private final DataTracker.Entry<UUID> targetPortalId = dataTracker.startTracking(TrackableDataType.UUID, Util.NIL_UUID);
|
||||
private final DataTracker.Entry<Float> targetPortalPitch = dataTracker.startTracking(TrackableDataType.FLOAT, 0F);
|
||||
private final DataTracker.Entry<Float> targetPortalYaw = dataTracker.startTracking(TrackableDataType.FLOAT, 0F);
|
||||
private final EntityReference<Entity> teleportationTarget = new EntityReference<>();
|
||||
private final EntityReference<Entity> teleportationTarget = dataTracker.startTracking(new EntityReference<>());
|
||||
|
||||
private final DataTracker.Entry<Float> pitch = dataTracker.startTracking(TrackableDataType.FLOAT, 0F);
|
||||
private final DataTracker.Entry<Float> yaw = dataTracker.startTracking(TrackableDataType.FLOAT, 0F);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,10 +25,11 @@ public class NaturalCloudBlock extends PoreousCloudBlock {
|
|||
public NaturalCloudBlock(Settings settings, boolean meltable,
|
||||
@Nullable Supplier<Soakable> soggyBlock,
|
||||
Supplier<Block> 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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<JarContents> 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));
|
||||
|
|
|
@ -30,15 +30,16 @@ public record ItemsJarContents (
|
|||
TileData tile,
|
||||
List<ItemStack> 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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
|
@ -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
|
||||
|
|
|
@ -51,8 +51,8 @@ public class UHud {
|
|||
|
||||
private final List<Slot> 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;
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -49,7 +49,9 @@ public class AmuletFeatureRenderer<E extends LivingEntity> implements AccessoryF
|
|||
|
||||
VertexConsumer consumer = ItemRenderer.getArmorGlintConsumer(renderContext, RenderLayer.getArmorCutoutNoCull(texture), false, false);
|
||||
|
||||
if (context.getModel() instanceof BipedEntityModel) {
|
||||
model.setAngles(entity, context.getModel());
|
||||
}
|
||||
model.render(matrices, consumer, lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -67,10 +67,6 @@ class EntityReplacementManager implements Disguise {
|
|||
return disguise;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setDirty() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDead() {
|
||||
return false;
|
||||
|
|
|
@ -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,13 +76,10 @@ 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);
|
||||
if (!MathHelper.approximatelyEquals(corruption, 0)) {
|
||||
corruption = pony.getInterpolator().interpolate("corruption", corruption, 10);
|
||||
|
||||
corruption = 1 - corruption + 0.05F;
|
||||
|
@ -96,14 +88,11 @@ public class ViewportShader implements SynchronousResourceReloader, Identifiable
|
|||
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 {
|
||||
|
|
|
@ -19,19 +19,22 @@ public class BubbleSpellRenderer extends SpellRenderer<BubbleSpell> {
|
|||
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();
|
||||
|
|
|
@ -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<T extends Spell> {
|
|||
|
||||
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<T extends Spell> {
|
|||
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<T extends Spell> {
|
|||
}
|
||||
|
||||
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<T extends Spell> {
|
|||
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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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.<Set<String>>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));
|
||||
}))
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
})));
|
||||
}
|
||||
|
|
|
@ -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) {
|
||||
source.sendFeedback(() -> {
|
||||
Race spec = Pony.of(player).getSpecies();
|
||||
|
||||
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("");
|
||||
|
||||
boolean first = true;
|
||||
for (Race i : Race.REGISTRY) {
|
||||
if (i.availability().isGrantable() && !i.isUnset() && i.isPermitted(player)) {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<ServerCommandSource> create() {
|
||||
|
@ -78,7 +79,9 @@ class TraitCommand {
|
|||
float gravity = iplayer.getPhysics().getGravityModifier();
|
||||
|
||||
if (source.getPlayer() == player) {
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -127,7 +127,7 @@ public interface TrinketsDelegate {
|
|||
}
|
||||
|
||||
record EquippedStack(ItemStack stack, Runnable sendUpdate, Consumer<LivingEntity> 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));
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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.<Affliction>of(
|
||||
|
|
|
@ -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<Item> AUTUMN_CROPS = item("autumn_crops");
|
||||
TagKey<Item> WINTER_CROPS = item("winter_crops");
|
||||
TagKey<Item> SPRING_CROPS = item("spring_crops");
|
||||
TagKey<Item> SUMMER_CROPS = item("summer_crops");
|
||||
|
||||
private static TagKey<Item> item(String name) {
|
||||
return TagKey.of(RegistryKeys.ITEM, new Identifier("sereneseasons", name));
|
||||
}
|
||||
}
|
||||
|
||||
interface Blocks {
|
||||
TagKey<Block> AUTUMN_CROPS = block("autumn_crops");
|
||||
TagKey<Block> WINTER_CROPS = block("winter_crops");
|
||||
TagKey<Block> SPRING_CROPS = block("spring_crops");
|
||||
TagKey<Block> SUMMER_CROPS = block("summer_crops");
|
||||
|
||||
private static TagKey<Block> block(String name) {
|
||||
return TagKey.of(RegistryKeys.BLOCK, new Identifier("sereneseasons", name));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -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() {
|
||||
|
|
|
@ -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<DamageType> {
|
|||
).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<DamageType> {
|
|||
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,
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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<LivingEntity> 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<LivingEntity> 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()) {
|
||||
|
|
|
@ -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<T extends Entity> implements Physics, Copyable<EntityPhysics<T>>, Tickable {
|
||||
|
@ -75,18 +75,17 @@ public class EntityPhysics<T extends Entity> implements Physics, Copyable<Entity
|
|||
|
||||
@Override
|
||||
public BlockPos getHeadPosition() {
|
||||
|
||||
BlockPos pos = new BlockPos(
|
||||
MathHelper.floor(entity.getX()),
|
||||
MathHelper.floor(entity.getY() + entity.getHeight() + 0.20000000298023224D),
|
||||
MathHelper.floor(entity.getZ())
|
||||
BlockPos pos = BlockPos.ofFloored(
|
||||
entity.getX(),
|
||||
entity.getY() + entity.getEyeHeight(EntityPose.STANDING),
|
||||
entity.getZ()
|
||||
);
|
||||
|
||||
if (entity.getWorld().getBlockState(pos).isAir()) {
|
||||
BlockPos below = pos.down();
|
||||
BlockState block = entity.getWorld().getBlockState(below);
|
||||
if (block.isIn(BlockTags.FENCES) || block.isIn(BlockTags.WALLS) || block.getBlock() instanceof FenceGateBlock) {
|
||||
return below;
|
||||
// return below;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -381,7 +381,7 @@ public abstract class Living<T extends LivingEntity> implements Equine<T>, 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);
|
||||
}
|
||||
|
||||
|
|
|
@ -49,6 +49,7 @@ public class BreakHeartGoal extends Goal {
|
|||
public void stop() {
|
||||
targetter.stop();
|
||||
mob.getNavigation().stop();
|
||||
mob.setTarget(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -24,8 +24,6 @@ public interface Disguise extends FlightType.Provider, PlayerDimensions.Provider
|
|||
|
||||
EntityAppearance getDisguise();
|
||||
|
||||
void setDirty();
|
||||
|
||||
boolean isDead();
|
||||
|
||||
default Optional<EntityAppearance> getAppearance() {
|
||||
|
@ -57,7 +55,6 @@ public interface Disguise extends FlightType.Provider, PlayerDimensions.Provider
|
|||
}
|
||||
|
||||
getDisguise().setAppearance(entity);
|
||||
setDirty();
|
||||
return this;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<EntityAppearance> {
|
||||
private static final Optional<Float> 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();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -65,7 +65,7 @@ public class SheepBehaviour extends EntityBehaviour<SheepEntity> {
|
|||
}
|
||||
} while (dropAmount-- > 0);
|
||||
}
|
||||
spell.setDirty();
|
||||
spell.getAppearance().ifPresent(EntityAppearance::markDirty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -89,6 +89,9 @@ public class CorruptInfluenceStatusEffect extends StatusEffect {
|
|||
}
|
||||
}
|
||||
|
||||
if (mob.getRandom().nextInt(4) != 0) {
|
||||
clone.clearStatusEffects();
|
||||
}
|
||||
mob.getWorld().spawnEntity(clone);
|
||||
|
||||
if (!mob.isSilent()) {
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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<CastS
|
|||
this.controllingEntityUuid = caster.asEntity().getUuid();
|
||||
this.controllingSpellUuid = control.getUuid();
|
||||
setCaster(caster);
|
||||
Spell spell = Spell.copy(control.getDelegate());
|
||||
spells.getSlots().put(spell);
|
||||
|
||||
if (control.getDelegate() instanceof PlacementDelegate delegate) {
|
||||
delegate.onPlaced(caster, control);
|
||||
}
|
||||
|
||||
spells.getSlots().put(Spell.copy(control.getDelegate()));
|
||||
}
|
||||
|
||||
public CastSpellEntity(EntityType<?> type, World world) {
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
@ -242,7 +242,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> 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<PlayerEntity> implements Tickab
|
|||
pony.getMagicalReserves().getCharge().set(0);
|
||||
}
|
||||
|
||||
if (!creative) {
|
||||
if (!creative && !pony.isClient()) {
|
||||
checkAvianTakeoffConditions(velocity);
|
||||
}
|
||||
}
|
||||
|
@ -377,16 +377,17 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> 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<PlayerEntity> 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<PlayerEntity> 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<PlayerEntity> 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<PlayerEntity> 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<PlayerEntity> 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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -224,6 +224,11 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, 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<PlayerEntity> implements Copyable<Pony>, 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<PlayerEntity> implements Copyable<Pony>, 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<PlayerEntity> implements Copyable<Pony>, 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;
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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<EntityAttribute, EntityAttributeModifier> attributeModifiers;
|
||||
|
@ -65,4 +68,9 @@ public class PolearmItem extends SwordItem {
|
|||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isAcceptableEnchant(ItemStack stack, Enchantment enchantment) {
|
||||
return enchantment != Enchantments.SWEEPING;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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,17 +31,20 @@ public class SpellbookItem extends BookItem implements Dispensable {
|
|||
}
|
||||
|
||||
@Override
|
||||
public TypedActionResult<ItemStack> dispenseStack(BlockPointer source, ItemStack stack) {
|
||||
Direction facing = source.state().get(DispenserBlock.FACING);
|
||||
BlockPos pos = source.pos().offset(facing);
|
||||
public TypedActionResult<ItemStack> 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);
|
||||
if (placeBook(stack, pointer.world(), pos, yaw, null)) {
|
||||
stack.decrement(1);
|
||||
|
||||
return new TypedActionResult<>(ActionResult.SUCCESS, stack);
|
||||
}
|
||||
|
||||
return new TypedActionResult<>(ActionResult.FAIL, stack);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ActionResult useOnBlock(ItemUsageContext context) {
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
|
@ -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<Boolean> info) {
|
||||
if (stack.getItem() instanceof CustomEnchantableItem item && !item.isAcceptableEnchant(stack, (Enchantment)(Object)this)) {
|
||||
info.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<List<EnchantmentLevelEntry>> info) {
|
||||
info.getReturnValue().removeIf(entry -> !entry.enchantment.isAcceptableItem(stack));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Boolean> info) {
|
||||
if (state.getBlock() instanceof CloudLike) {
|
||||
info.setReturnValue(false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -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<BlockDestructionManager> 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<Float> 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<Float> info) {
|
||||
if (rainGradientOverride != null) {
|
||||
info.setReturnValue(rainGradientOverride);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(method = "hasRain", at = @At("RETURN"), cancellable = true)
|
||||
private void onHasRain(BlockPos pos, CallbackInfoReturnable<Boolean> info) {
|
||||
info.setReturnValue((info.getReturnValue() && isBelowCloudLayer(pos)) || isInRangeOfStorm(pos));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Float> 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<Float> 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",
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue