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"
|
include "com.sollace:Romanizer:Romanizer:1.0.2"
|
||||||
|
|
||||||
modCompileOnly "com.terraformersmc:modmenu:${project.modmenu_version}"
|
modCompileOnly "com.terraformersmc:modmenu:${project.modmenu_version}"
|
||||||
|
|
||||||
|
if (project.use_trinkets == '1') {
|
||||||
modCompileOnly "dev.emi:trinkets:${project.trinkets_version}"
|
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-base:5.3.0"
|
||||||
modCompileOnly "dev.onyxstudios.cardinal-components-api:cardinal-components-entity: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}"
|
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}"
|
include "com.terraformersmc.terraform-api:terraform-wood-api-v1:${project.terraformer_api_version}"
|
||||||
|
@ -98,7 +103,12 @@ dependencies {
|
||||||
if (project.use_sodium == '1') {
|
if (project.use_sodium == '1') {
|
||||||
modCompileOnly "maven.modrinth:indium:${project.indium_version}", { exclude group: "net.fabricmc.fabric-api" }
|
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: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') {
|
if (project.tmi_type == 'emi') {
|
||||||
|
|
|
@ -30,8 +30,10 @@ org.gradle.daemon=false
|
||||||
nodium_version=1.1.0+1.20
|
nodium_version=1.1.0+1.20
|
||||||
|
|
||||||
# Testing
|
# Testing
|
||||||
|
use_trinkets=1
|
||||||
use_pehkui=0
|
use_pehkui=0
|
||||||
use_sodium=0
|
use_sodium=0
|
||||||
|
use_iris=1
|
||||||
|
|
||||||
farmers_delight_version=1.20.1-2.0.9
|
farmers_delight_version=1.20.1-2.0.9
|
||||||
pehkui_version=3.7.8+1.14.4-1.20.2
|
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() {
|
default boolean collidesWithClouds() {
|
||||||
return getCompositeRace().canInteractWithClouds();
|
return getCompositeRace().canInteractWithClouds() || getCloudWalkingStrength() >= 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
default boolean hasFeatherTouch() {
|
default boolean hasFeatherTouch() {
|
||||||
|
|
|
@ -2,6 +2,7 @@ package com.minelittlepony.unicopia;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
import java.util.Stack;
|
||||||
import java.util.UUID;
|
import java.util.UUID;
|
||||||
|
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.annotations.NotNull;
|
||||||
|
@ -37,7 +38,7 @@ public class InteractionManager {
|
||||||
@Nullable
|
@Nullable
|
||||||
private SyncedConfig config;
|
private SyncedConfig config;
|
||||||
|
|
||||||
private EquineContext equineContext = EquineContext.ABSENT;
|
private final Stack<EquineContext> equineContext = new Stack<>();
|
||||||
|
|
||||||
public static InteractionManager getInstance() {
|
public static InteractionManager getInstance() {
|
||||||
return INSTANCE;
|
return INSTANCE;
|
||||||
|
@ -109,11 +110,21 @@ public class InteractionManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setEquineContext(EquineContext context) {
|
public void setEquineContext(EquineContext context) {
|
||||||
equineContext = context;
|
equineContext.push(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void clearEquineContext() {
|
||||||
|
if (!equineContext.isEmpty()) {
|
||||||
|
equineContext.pop();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public EquineContext getEquineContext() {
|
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() {
|
public Optional<Pony> getClientPony() {
|
||||||
|
|
|
@ -70,7 +70,7 @@ public record Race (
|
||||||
* This is used if there are no other races.
|
* 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 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()
|
public static final Race EARTH = register("earth", new Builder().foraging().earth()
|
||||||
.abilities(Abilities.HUG, Abilities.STOMP, Abilities.KICK, Abilities.GROW)
|
.abilities(Abilities.HUG, Abilities.STOMP, Abilities.KICK, Abilities.GROW)
|
||||||
);
|
);
|
||||||
|
|
|
@ -46,6 +46,7 @@ public interface UConventionalTags {
|
||||||
TagKey<Item> FRUITS = item("fruits");
|
TagKey<Item> FRUITS = item("fruits");
|
||||||
TagKey<Item> WORMS = item("worms");
|
TagKey<Item> WORMS = item("worms");
|
||||||
TagKey<Item> ROCKS = item("rocks");
|
TagKey<Item> ROCKS = item("rocks");
|
||||||
|
TagKey<Item> GEMS = item("gems");
|
||||||
|
|
||||||
TagKey<Item> RAW_INSECT = item("raw_insect");
|
TagKey<Item> RAW_INSECT = item("raw_insect");
|
||||||
TagKey<Item> COOKED_INSECT = item("cooked_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.network.Channel;
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
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.NocturnalSleepManager;
|
||||||
import com.minelittlepony.unicopia.server.world.UGameRules;
|
import com.minelittlepony.unicopia.server.world.UGameRules;
|
||||||
import com.minelittlepony.unicopia.server.world.UWorldGen;
|
import com.minelittlepony.unicopia.server.world.UWorldGen;
|
||||||
|
@ -71,6 +72,7 @@ public class Unicopia implements ModInitializer {
|
||||||
((BlockDestructionManager.Source)w).getDestructionManager().tick();
|
((BlockDestructionManager.Source)w).getDestructionManager().tick();
|
||||||
ZapAppleStageStore.get(w).tick();
|
ZapAppleStageStore.get(w).tick();
|
||||||
WeatherConditions.get(w).tick();
|
WeatherConditions.get(w).tick();
|
||||||
|
Ether.get(w).tick();
|
||||||
if (Debug.SPELLBOOK_CHAPTERS) {
|
if (Debug.SPELLBOOK_CHAPTERS) {
|
||||||
SpellbookChapterLoader.INSTANCE.sendUpdate(w.getServer());
|
SpellbookChapterLoader.INSTANCE.sendUpdate(w.getServer());
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,7 +37,7 @@ public class BatPonyHangAbility implements Ability<Multi> {
|
||||||
}
|
}
|
||||||
|
|
||||||
return TraceHelper.findBlock(player.asEntity(), 5, 1)
|
return TraceHelper.findBlock(player.asEntity(), 5, 1)
|
||||||
.map(BlockPos::down)
|
.map(pos -> pos.down(player.getPhysics().getGravitySignum()))
|
||||||
.filter(player.getAcrobatics()::canHangAt)
|
.filter(player.getAcrobatics()::canHangAt)
|
||||||
.map(pos -> new Multi(pos, 1));
|
.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.TransformCropsRecipe;
|
||||||
import com.minelittlepony.unicopia.recipe.URecipes;
|
import com.minelittlepony.unicopia.recipe.URecipes;
|
||||||
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
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.TraceHelper;
|
||||||
import com.minelittlepony.unicopia.util.VecHelper;
|
import com.minelittlepony.unicopia.util.VecHelper;
|
||||||
|
|
||||||
|
@ -70,8 +71,10 @@ public class EarthPonyGrowAbility implements Ability<Pos> {
|
||||||
for (BlockPos pos : BlockPos.iterate(
|
for (BlockPos pos : BlockPos.iterate(
|
||||||
data.pos().add(-2, -2, -2),
|
data.pos().add(-2, -2, -2),
|
||||||
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);
|
count += applySingle(player, player.asWorld(), player.asWorld().getBlockState(pos), pos);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
count = 1;
|
count = 1;
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,6 +17,7 @@ import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
import com.minelittlepony.unicopia.particle.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
||||||
|
import com.minelittlepony.unicopia.server.world.ModificationType;
|
||||||
import com.minelittlepony.unicopia.util.*;
|
import com.minelittlepony.unicopia.util.*;
|
||||||
|
|
||||||
import net.minecraft.block.BeehiveBlock;
|
import net.minecraft.block.BeehiveBlock;
|
||||||
|
@ -98,7 +99,7 @@ public class EarthPonyKickAbility implements Ability<Pos> {
|
||||||
}
|
}
|
||||||
|
|
||||||
BlockPos pos = kickLocation.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);
|
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 (BlockDestructionManager.of(player.getWorld()).getBlockDestruction(pos) + 4 >= BlockDestructionManager.MAX_DAMAGE) {
|
||||||
if (player.getWorld().random.nextInt(30) == 0) {
|
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) -> {
|
tree.leaves().forEach(player.getWorld(), (w, state, p) -> {
|
||||||
|
if (iplayer.canModifyAt(p, ModificationType.PHYSICAL)) {
|
||||||
Block.dropStacks(w.getBlockState(p), w, p);
|
Block.dropStacks(w.getBlockState(p), w, p);
|
||||||
w.setBlockState(p, Blocks.AIR.getDefaultState(), Block.NOTIFY_ALL);
|
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.ParticleUtils;
|
||||||
import com.minelittlepony.unicopia.particle.UParticles;
|
import com.minelittlepony.unicopia.particle.UParticles;
|
||||||
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
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.PosHelper;
|
||||||
import com.minelittlepony.unicopia.util.VecHelper;
|
import com.minelittlepony.unicopia.util.VecHelper;
|
||||||
|
|
||||||
|
@ -166,7 +167,7 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
||||||
|
|
||||||
double radius = rad + heavyness * 0.3;
|
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);
|
ParticleUtils.spawnParticle(player.getWorld(), UParticles.GROUND_POUND, player.getX(), player.getY() - 1, player.getZ(), 0, 0, 0);
|
||||||
BlockState steppingState = player.getSteppingBlockState();
|
BlockState steppingState = player.getSteppingBlockState();
|
||||||
|
@ -198,17 +199,17 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
||||||
return true;
|
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 -> {
|
BlockPos.stream(new BlockBox(center).expand(MathHelper.ceil(radius))).forEach(i -> {
|
||||||
double dist = Math.sqrt(i.getSquaredDistance(source.getX(), source.getY(), source.getZ()));
|
double dist = Math.sqrt(i.getSquaredDistance(source.getX(), source.getY(), source.getZ()));
|
||||||
|
|
||||||
if (dist <= radius) {
|
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()) {
|
if (w.getBlockState(pos.up()).isAir()) {
|
||||||
BlockState state = w.getBlockState(pos);
|
BlockState state = w.getBlockState(pos);
|
||||||
|
|
||||||
|
@ -216,18 +217,18 @@ public class EarthPonyStompAbility implements Ability<Hit> {
|
||||||
float scaledHardness = (1 - hardness / 70);
|
float scaledHardness = (1 - hardness / 70);
|
||||||
float damage = hardness < 0 ? 0 : MathHelper.clamp((int)((1 - dist / rad) * 9 * scaledHardness), 0, BlockDestructionManager.MAX_DAMAGE - 1);
|
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);
|
BlockState state = w.getBlockState(pos);
|
||||||
|
|
||||||
if (state.isAir() || damage <= 0) {
|
if (state.isAir() || damage <= 0) {
|
||||||
return;
|
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);
|
w.breakBlock(pos, true);
|
||||||
|
|
||||||
if (w instanceof ServerWorld) {
|
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.data.Numeric;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
import com.minelittlepony.unicopia.advancement.UCriteria;
|
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.client.render.PlayerPoser.Animation;
|
||||||
import com.minelittlepony.unicopia.entity.Living;
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
|
||||||
|
@ -126,8 +127,10 @@ public class ScreechAbility implements Ability<Numeric> {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void coolDown(Pony player, AbilitySlot slot) {
|
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++) {
|
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)
|
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 com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
public class ToggleFlightAbility implements Ability<Hit> {
|
public class ToggleFlightAbility implements Ability<Hit> {
|
||||||
|
|
||||||
|
@ -27,7 +28,7 @@ public class ToggleFlightAbility implements Ability<Hit> {
|
||||||
@Nullable
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public Optional<Hit> prepare(Pony player) {
|
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
|
@Override
|
||||||
|
@ -59,6 +60,11 @@ public class ToggleFlightAbility implements Ability<Hit> {
|
||||||
player.subtractEnergyCost(1);
|
player.subtractEnergyCost(1);
|
||||||
|
|
||||||
if (!player.getPhysics().isFlying()) {
|
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);
|
player.asEntity().addVelocity(0, player.getPhysics().getGravitySignum() * 0.7F, 0);
|
||||||
Living.updateVelocity(player.asEntity());
|
Living.updateVelocity(player.asEntity());
|
||||||
player.getPhysics().startFlying(true);
|
player.getPhysics().startFlying(true);
|
||||||
|
|
|
@ -116,6 +116,9 @@ class MultiSpellSlot implements SpellSlots, NbtSerialisable {
|
||||||
if (s != null) {
|
if (s != null) {
|
||||||
s.setDead();
|
s.setDead();
|
||||||
s.tickDying(owner);
|
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 hasValue ? Status.NEW : Status.REMOVED;
|
||||||
}
|
}
|
||||||
|
|
||||||
return spell.hasDirtySpell() ? Status.UPDATED : Status.DEFAULT;
|
return Status.DEFAULT;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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.effect.*;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
|
||||||
|
|
||||||
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
public abstract class AbstractAreaEffectSpell extends AbstractSpell {
|
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;
|
public static final TooltipFactory TOOLTIP = RANGE;
|
||||||
|
|
||||||
protected AbstractAreaEffectSpell(CustomisedSpellType<?> type) {
|
protected AbstractAreaEffectSpell(CustomisedSpellType<?> type) {
|
||||||
|
|
|
@ -80,18 +80,6 @@ public abstract class AbstractDelegatingSpell implements Spell {
|
||||||
return getOrEmpty().isDying();
|
return getOrEmpty().isDying();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
|
||||||
public boolean isDirty() {
|
|
||||||
return delegate.hasDirtySpell();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
|
||||||
public void setDirty() {
|
|
||||||
getOrEmpty().setDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isHidden() {
|
public boolean isHidden() {
|
||||||
return getOrEmpty().isHidden();
|
return getOrEmpty().isHidden();
|
||||||
|
|
|
@ -20,7 +20,7 @@ import net.minecraft.nbt.NbtCompound;
|
||||||
*/
|
*/
|
||||||
public abstract class AbstractDisguiseSpell extends AbstractSpell implements Disguise, ProjectileImpactListener {
|
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) {
|
public AbstractDisguiseSpell(CustomisedSpellType<?> type) {
|
||||||
super(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 final DataTracker.Entry<Boolean> suppressed = dataTracker.startTracking(TrackableDataType.BOOLEAN, false);
|
||||||
private int suppressionCounter;
|
private int suppressionCounter;
|
||||||
|
|
||||||
|
private boolean forced;
|
||||||
|
|
||||||
public DispersableDisguiseSpell(CustomisedSpellType<?> type) {
|
public DispersableDisguiseSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
setHidden(true);
|
setHidden(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setForced() {
|
||||||
|
forced = true;
|
||||||
|
setHidden(false);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isVulnerable(Caster<?> otherSource, Spell other) {
|
public boolean isVulnerable(Caster<?> otherSource, Spell other) {
|
||||||
return suppressionCounter <= otherSource.getLevel().get();
|
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();
|
setDead();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -91,12 +98,14 @@ public class DispersableDisguiseSpell extends AbstractDisguiseSpell implements I
|
||||||
public void toNBT(NbtCompound compound) {
|
public void toNBT(NbtCompound compound) {
|
||||||
super.toNBT(compound);
|
super.toNBT(compound);
|
||||||
compound.putInt("suppressionCounter", suppressionCounter);
|
compound.putInt("suppressionCounter", suppressionCounter);
|
||||||
|
compound.putBoolean("forced", forced);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fromNBT(NbtCompound compound) {
|
public void fromNBT(NbtCompound compound) {
|
||||||
super.fromNBT(compound);
|
super.fromNBT(compound);
|
||||||
suppressionCounter = compound.getInt("suppressionCounter");
|
suppressionCounter = compound.getInt("suppressionCounter");
|
||||||
|
forced = compound.getBoolean("forced");
|
||||||
if (suppressionCounter > 0) {
|
if (suppressionCounter > 0) {
|
||||||
suppressed.set(true);
|
suppressed.set(true);
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,11 +44,6 @@ public final class EmptySpell implements Spell {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isDirty() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tick(Caster<?> caster, Situation situation) {
|
public boolean tick(Caster<?> caster, Situation situation) {
|
||||||
return false;
|
return false;
|
||||||
|
@ -57,9 +52,6 @@ public final class EmptySpell implements Spell {
|
||||||
@Override
|
@Override
|
||||||
public void tickDying(Caster<?> caster) { }
|
public void tickDying(Caster<?> caster) { }
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDirty() { }
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isHidden() {
|
public boolean isHidden() {
|
||||||
return true;
|
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.CustomisedSpellType;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
|
||||||
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
|
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.server.world.Ether;
|
||||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||||
|
|
||||||
|
@ -21,12 +23,10 @@ import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class PlacementControlSpell extends AbstractSpell implements OrientedSpell {
|
public class PlacementControlSpell extends AbstractSpell implements OrientedSpell {
|
||||||
@Nullable
|
private final DataTracker.Entry<UUID> placedEntityId = dataTracker.startTracking(TrackableDataType.UUID, null);
|
||||||
private UUID placedEntityId;
|
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 Optional<RegistryKey<World>> dimension = Optional.empty();
|
private final DataTracker.Entry<Optional<Vec3d>> orientation = dataTracker.startTracking(TrackableDataType.OPTIONAL_VECTOR, Optional.empty());
|
||||||
private Optional<Vec3d> position = Optional.empty();
|
|
||||||
private Optional<Vec3d> orientation = Optional.empty();
|
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Spell delegate;
|
private Spell delegate;
|
||||||
|
@ -46,26 +46,23 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel
|
||||||
}
|
}
|
||||||
|
|
||||||
public Optional<Vec3d> getPosition() {
|
public Optional<Vec3d> getPosition() {
|
||||||
return position;
|
return position.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setDimension(RegistryKey<World> dimension) {
|
public void setDimension(RegistryKey<World> dimension) {
|
||||||
this.dimension = Optional.of(dimension);
|
this.dimension.set(Optional.of(dimension));
|
||||||
setDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void setPosition(Vec3d position) {
|
public void setPosition(Vec3d position) {
|
||||||
this.position = Optional.of(position);
|
this.position.set(Optional.of(position));
|
||||||
setDirty();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setOrientation(Caster<?> caster, float pitch, float yaw) {
|
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) {
|
if (delegate instanceof OrientedSpell o) {
|
||||||
o.setOrientation(caster, pitch, yaw);
|
o.setOrientation(caster, pitch, yaw);
|
||||||
}
|
}
|
||||||
setDirty();
|
|
||||||
if (!caster.isClient()) {
|
if (!caster.isClient()) {
|
||||||
var entry = getConnection(caster);
|
var entry = getConnection(caster);
|
||||||
if (entry != null) {
|
if (entry != null) {
|
||||||
|
@ -77,62 +74,60 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Caster<?> caster) {
|
public boolean apply(Caster<?> caster) {
|
||||||
if (delegate == null) {
|
return delegate != null && super.apply(caster);
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean tick(Caster<?> source, Situation situation) {
|
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();
|
setDead();
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return !isDead();
|
return !isDead();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
private Ether.Entry<?> getConnection(Caster<?> source) {
|
private Ether.Entry<?> getConnection(Caster<?> source) {
|
||||||
return delegate == null || placedEntityId == null ? null : getWorld(source)
|
return delegate == null || placedEntityId.get() == null ? null : getWorld(source)
|
||||||
.map(world -> Ether.get(world).get(getDelegate().getTypeAndTraits().type(), placedEntityId, delegate.getUuid()))
|
.map(world -> Ether.get(world).get(getDelegate().getTypeAndTraits().type(), placedEntityId.get(), delegate.getUuid()))
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Optional<World> getWorld(Caster<?> source) {
|
private Optional<World> getWorld(Caster<?> source) {
|
||||||
return dimension.map(source.asWorld().getServer()::getWorld);
|
return dimension.get().map(source.asWorld().getServer()::getWorld);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void toNBT(NbtCompound compound) {
|
public void toNBT(NbtCompound compound) {
|
||||||
super.toNBT(compound);
|
super.toNBT(compound);
|
||||||
compound.put("spell", Spell.writeNbt(delegate));
|
compound.put("spell", Spell.writeNbt(delegate));
|
||||||
position.ifPresent(pos -> compound.put("position", NbtSerialisable.writeVector(pos)));
|
position.get().ifPresent(pos -> compound.put("position", NbtSerialisable.writeVector(pos)));
|
||||||
orientation.ifPresent(o -> compound.put("orientation", NbtSerialisable.writeVector(o)));
|
orientation.get().ifPresent(o -> compound.put("orientation", NbtSerialisable.writeVector(o)));
|
||||||
dimension.ifPresent(d -> compound.putString("dimension", d.getValue().toString()));
|
dimension.get().ifPresent(d -> compound.putString("dimension", d.getValue().toString()));
|
||||||
if (placedEntityId != null) {
|
if (placedEntityId.get() != null) {
|
||||||
compound.putUuid("placedEntityId", placedEntityId);
|
compound.putUuid("placedEntityId", placedEntityId.get());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -140,12 +135,10 @@ public class PlacementControlSpell extends AbstractSpell implements OrientedSpel
|
||||||
public void fromNBT(NbtCompound compound) {
|
public void fromNBT(NbtCompound compound) {
|
||||||
super.fromNBT(compound);
|
super.fromNBT(compound);
|
||||||
delegate = Spell.readNbt(compound.getCompound("spell"));
|
delegate = Spell.readNbt(compound.getCompound("spell"));
|
||||||
placedEntityId = compound.containsUuid("placedEntityId") ? compound.getUuid("placedEntityId") : null;
|
placedEntityId.set(compound.containsUuid("placedEntityId") ? compound.getUuid("placedEntityId") : null);
|
||||||
position = compound.contains("position") ? Optional.of(NbtSerialisable.readVector(compound.getList("position", NbtElement.DOUBLE_TYPE))) : Optional.empty();
|
position.set(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();
|
orientation.set(compound.contains("orientation") ? Optional.of(NbtSerialisable.readVector(compound.getList("orientation", NbtElement.DOUBLE_TYPE))) : Optional.empty());
|
||||||
if (compound.contains("dimension", NbtElement.STRING_TYPE)) {
|
dimension.set(compound.contains("dimension", NbtElement.STRING_TYPE) ? Optional.ofNullable(Identifier.tryParse(compound.getString("dimension"))).map(id -> RegistryKey.of(RegistryKeys.WORLD, id)) : Optional.empty());
|
||||||
dimension = Optional.ofNullable(Identifier.tryParse(compound.getString("dimension"))).map(id -> RegistryKey.of(RegistryKeys.WORLD, id));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public interface PlacementDelegate {
|
public interface PlacementDelegate {
|
||||||
|
|
|
@ -74,18 +74,6 @@ public interface Spell extends NbtSerialisable, Affine {
|
||||||
|
|
||||||
boolean isDying();
|
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.
|
* Applies this spell to the supplied caster.
|
||||||
* @param caster The caster to apply the spell to
|
* @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);
|
set(spell, null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
public boolean hasDirtySpell() {
|
|
||||||
return spell != null && spell.isDirty();
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean set(T spell, @Nullable Caster<?> owner) {
|
public boolean set(T spell, @Nullable Caster<?> owner) {
|
||||||
spell = spell == null || spell.isDead() ? null : spell;
|
spell = spell == null || spell.isDead() ? null : spell;
|
||||||
if (spell == this.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> dead = dataTracker.startTracking(TrackableDataType.BOOLEAN, false);
|
||||||
private final DataTracker.Entry<Boolean> dying = 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 final DataTracker.Entry<Boolean> hidden = dataTracker.startTracking(TrackableDataType.BOOLEAN, false);
|
||||||
private boolean destroyed;
|
private boolean destroyed;
|
||||||
|
|
||||||
|
@ -66,18 +65,6 @@ public abstract class AbstractSpell implements Spell {
|
||||||
return dying.get();
|
return dying.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
|
||||||
public final boolean isDirty() {
|
|
||||||
return dirty;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated
|
|
||||||
@Override
|
|
||||||
public final void setDirty() {
|
|
||||||
dirty = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public final boolean isHidden() {
|
public final boolean isHidden() {
|
||||||
return hidden.get();
|
return hidden.get();
|
||||||
|
@ -120,7 +107,6 @@ public abstract class AbstractSpell implements Spell {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fromNBT(NbtCompound compound) {
|
public void fromNBT(NbtCompound compound) {
|
||||||
dirty = false;
|
|
||||||
if (compound.containsUuid("uuid")) {
|
if (compound.containsUuid("uuid")) {
|
||||||
uuid = compound.getUuid("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 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);
|
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) {
|
protected AttractiveSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
timer = new Timer(TIME.get(getTraits()));
|
|
||||||
dataTracker.startTracking(target);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -19,11 +19,10 @@ import net.minecraft.registry.Registries;
|
||||||
|
|
||||||
public class AwkwardSpell extends AbstractSpell implements TimedSpell {
|
public class AwkwardSpell extends AbstractSpell implements TimedSpell {
|
||||||
|
|
||||||
private final Timer timer;
|
private final Timer timer = new Timer(20);
|
||||||
|
|
||||||
protected AwkwardSpell(CustomisedSpellType<?> type) {
|
protected AwkwardSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
timer = new Timer(20);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -56,17 +56,14 @@ public class BubbleSpell extends AbstractSpell implements TimedSpell,
|
||||||
|
|
||||||
static final TooltipFactory TOOLTIP = TooltipFactory.of(TimedSpell.TIME, SOAPINESS);
|
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 float prevRadius;
|
||||||
private DataTracker.Entry<Float> radius;
|
private DataTracker.Entry<Float> radius = dataTracker.startTracking(TrackableDataType.FLOAT, 0F);
|
||||||
private DataTracker.Entry<Integer> struggles;
|
private DataTracker.Entry<Integer> struggles = dataTracker.startTracking(TrackableDataType.INT, SOAPINESS.get(getTraits()));
|
||||||
|
|
||||||
protected BubbleSpell(CustomisedSpellType<?> type) {
|
protected BubbleSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
timer = new Timer(TIME.get(getTraits()));
|
|
||||||
radius = dataTracker.startTracking(TrackableDataType.FLOAT, 0F);
|
|
||||||
struggles = dataTracker.startTracking(TrackableDataType.INT, SOAPINESS.get(getTraits()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -18,13 +18,13 @@ import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.util.hit.EntityHitResult;
|
import net.minecraft.util.hit.EntityHitResult;
|
||||||
import net.minecraft.util.math.Vec3d;
|
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);
|
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;
|
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;
|
private int ticks = 10;
|
||||||
|
|
||||||
|
@ -34,7 +34,7 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Spell prepareForCast(Caster<?> caster, CastingMethod method) {
|
public Spell prepareForCast(Caster<?> caster, CastingMethod method) {
|
||||||
return toPlaceable();
|
return method.isIndirectCause() ? this : toPlaceable();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -43,14 +43,23 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro
|
||||||
|
|
||||||
originator.asEntity().setGlowing(true);
|
originator.asEntity().setGlowing(true);
|
||||||
|
|
||||||
|
if (situation == Situation.PROJECTILE) {
|
||||||
|
return !isDead();
|
||||||
|
}
|
||||||
|
|
||||||
ticks--;
|
ticks--;
|
||||||
|
|
||||||
if (originator.isClient()) {
|
if (originator.isClient()) {
|
||||||
return !isDead() || ticks >= -10;
|
return !isDead() || ticks >= -10;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!originator.isClient()) {
|
||||||
|
target.ifPresent(originator.asWorld(), target -> {
|
||||||
|
target.setGlowing(true);
|
||||||
if (ticks == 0) {
|
if (ticks == 0) {
|
||||||
target.ifPresent(originator.asWorld(), target -> apply(originator, target));
|
apply(originator, target);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return ticks >= -10;
|
return ticks >= -10;
|
||||||
|
@ -58,7 +67,18 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onImpact(MagicProjectileEntity projectile, EntityHitResult hit) {
|
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) {
|
private void apply(Caster<?> originator, Entity target) {
|
||||||
|
@ -107,11 +127,13 @@ public class DisplacementSpell extends AbstractSpell implements HomingSpell, Pro
|
||||||
public void toNBT(NbtCompound compound) {
|
public void toNBT(NbtCompound compound) {
|
||||||
super.toNBT(compound);
|
super.toNBT(compound);
|
||||||
compound.putInt("ticks", ticks);
|
compound.putInt("ticks", ticks);
|
||||||
|
compound.put("target", target.toNBT());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void fromNBT(NbtCompound compound) {
|
public void fromNBT(NbtCompound compound) {
|
||||||
super.fromNBT(compound);
|
super.fromNBT(compound);
|
||||||
ticks = compound.getInt("ticks");
|
ticks = compound.getInt("ticks");
|
||||||
|
target.fromNBT(compound.getCompound("target"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,11 +59,10 @@ public class FeatherFallSpell extends AbstractSpell implements TimedSpell {
|
||||||
.with(Trait.ORDER, 15)
|
.with(Trait.ORDER, 15)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
private final Timer timer;
|
private final Timer timer = new Timer(DURATION.get(getTraits()));
|
||||||
|
|
||||||
protected FeatherFallSpell(CustomisedSpellType<?> type) {
|
protected FeatherFallSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
timer = new Timer(DURATION.get(getTraits()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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));
|
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) {
|
protected FireBoltSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
|
|
|
@ -38,13 +38,12 @@ public class LightSpell extends AbstractSpell implements TimedSpell, ProjectileD
|
||||||
|
|
||||||
static final TooltipFactory TOOLTIP = TooltipFactory.of(TIME, ORB_COUNT);
|
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<>();
|
private final List<EntityReference<FairyEntity>> lights = new ArrayList<>();
|
||||||
|
|
||||||
protected LightSpell(CustomisedSpellType<?> type) {
|
protected LightSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
timer = new Timer(TIME.get(getTraits()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -11,11 +11,10 @@ public class MimicSpell extends AbstractDisguiseSpell implements HomingSpell, Ti
|
||||||
|
|
||||||
static final TooltipFactory TOOLTIP = TimedSpell.TIME;
|
static final TooltipFactory TOOLTIP = TimedSpell.TIME;
|
||||||
|
|
||||||
private final Timer timer;
|
private final Timer timer = new Timer(TIME.get(getTraits()));
|
||||||
|
|
||||||
protected MimicSpell(CustomisedSpellType<?> type) {
|
protected MimicSpell(CustomisedSpellType<?> type) {
|
||||||
super(type);
|
super(type);
|
||||||
timer = new Timer(TIME.get(getTraits()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@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<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> targetPortalPitch = dataTracker.startTracking(TrackableDataType.FLOAT, 0F);
|
||||||
private final DataTracker.Entry<Float> targetPortalYaw = 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> pitch = dataTracker.startTracking(TrackableDataType.FLOAT, 0F);
|
||||||
private final DataTracker.Entry<Float> yaw = 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) {
|
if (world.random.nextInt(10) == 0) {
|
||||||
player.playSound(USounds.Vanilla.ENTITY_PLAYER_BURP, 1, player.getSoundPitch());
|
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;
|
return ActionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class CloudBedBlock extends FancyBedBlock implements CloudLike {
|
||||||
private final CloudBlock baseBlock;
|
private final CloudBlock baseBlock;
|
||||||
|
|
||||||
public CloudBedBlock(String base, BlockState baseState, Settings settings) {
|
public CloudBedBlock(String base, BlockState baseState, Settings settings) {
|
||||||
super(base, settings.dynamicBounds());
|
super(base, CloudLike.applyCloudProperties(settings));
|
||||||
this.baseState = baseState;
|
this.baseState = baseState;
|
||||||
this.baseBlock = (CloudBlock)baseState.getBlock();
|
this.baseBlock = (CloudBlock)baseState.getBlock();
|
||||||
}
|
}
|
||||||
|
@ -75,6 +75,6 @@ public class CloudBedBlock extends FancyBedBlock implements CloudLike {
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
|
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 org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquineContext;
|
import com.minelittlepony.unicopia.EquineContext;
|
||||||
|
import com.minelittlepony.unicopia.InteractionManager;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
|
@ -30,10 +31,21 @@ public class CloudBlock extends Block implements CloudLike {
|
||||||
protected final boolean meltable;
|
protected final boolean meltable;
|
||||||
|
|
||||||
public CloudBlock(Settings settings, 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;
|
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
|
@Override
|
||||||
public void onEntityLand(BlockView world, Entity entity) {
|
public void onEntityLand(BlockView world, Entity entity) {
|
||||||
boolean bounce = Math.abs(entity.getVelocity().y) > 0.3;
|
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.addVelocity(0, 0.07, 0);
|
||||||
entity.setOnGround(true);
|
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
|
@Override
|
||||||
|
@ -163,7 +174,8 @@ public class CloudBlock extends Block implements CloudLike {
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
|
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) {
|
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 org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquineContext;
|
import com.minelittlepony.unicopia.EquineContext;
|
||||||
|
import com.minelittlepony.unicopia.InteractionManager;
|
||||||
import com.minelittlepony.unicopia.block.UBlockEntities;
|
import com.minelittlepony.unicopia.block.UBlockEntities;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.ChestBlock;
|
import net.minecraft.block.ChestBlock;
|
||||||
|
@ -77,7 +78,7 @@ public class CloudChestBlock extends ChestBlock implements CloudLike {
|
||||||
};
|
};
|
||||||
|
|
||||||
public CloudChestBlock(Settings settings, BlockState baseState) {
|
public CloudChestBlock(Settings settings, BlockState baseState) {
|
||||||
super(settings.dynamicBounds(), () -> UBlockEntities.CLOUD_CHEST);
|
super(CloudLike.applyCloudProperties(settings), () -> UBlockEntities.CLOUD_CHEST);
|
||||||
this.baseState = baseState;
|
this.baseState = baseState;
|
||||||
this.baseBlock = (CloudBlock)baseState.getBlock();
|
this.baseBlock = (CloudBlock)baseState.getBlock();
|
||||||
}
|
}
|
||||||
|
@ -139,7 +140,7 @@ public class CloudChestBlock extends ChestBlock implements CloudLike {
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
|
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 {
|
public static class TileData extends ChestBlockEntity {
|
||||||
|
|
|
@ -3,6 +3,7 @@ package com.minelittlepony.unicopia.block.cloud;
|
||||||
import org.jetbrains.annotations.Nullable;
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquineContext;
|
import com.minelittlepony.unicopia.EquineContext;
|
||||||
|
import com.minelittlepony.unicopia.InteractionManager;
|
||||||
import com.minelittlepony.unicopia.Race;
|
import com.minelittlepony.unicopia.Race;
|
||||||
|
|
||||||
import net.minecraft.block.BlockSetType;
|
import net.minecraft.block.BlockSetType;
|
||||||
|
@ -10,6 +11,7 @@ import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.DoorBlock;
|
import net.minecraft.block.DoorBlock;
|
||||||
import net.minecraft.block.ShapeContext;
|
import net.minecraft.block.ShapeContext;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.ai.pathing.NavigationType;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemPlacementContext;
|
import net.minecraft.item.ItemPlacementContext;
|
||||||
import net.minecraft.util.ActionResult;
|
import net.minecraft.util.ActionResult;
|
||||||
|
@ -26,7 +28,7 @@ public class CloudDoorBlock extends DoorBlock implements CloudLike {
|
||||||
private final CloudBlock baseBlock;
|
private final CloudBlock baseBlock;
|
||||||
|
|
||||||
public CloudDoorBlock(Settings settings, BlockState baseState, BlockSetType blockSet) {
|
public CloudDoorBlock(Settings settings, BlockState baseState, BlockSetType blockSet) {
|
||||||
super(settings.dynamicBounds(), blockSet);
|
super(CloudLike.applyCloudProperties(settings), blockSet);
|
||||||
this.baseState = baseState;
|
this.baseState = baseState;
|
||||||
this.baseBlock = (CloudBlock)baseState.getBlock();
|
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));
|
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;
|
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;
|
private final CloudBlock baseBlock;
|
||||||
|
|
||||||
public CloudStairsBlock(BlockState baseState, Settings settings) {
|
public CloudStairsBlock(BlockState baseState, Settings settings) {
|
||||||
super(baseState, settings.dynamicBounds());
|
super(baseState, CloudLike.applyCloudProperties(settings));
|
||||||
this.baseBlock = (CloudBlock)baseState.getBlock();
|
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
|
@Override
|
||||||
public void onEntityLand(BlockView world, Entity entity) {
|
public void onEntityLand(BlockView world, Entity entity) {
|
||||||
baseBlock.onEntityLand(world, entity);
|
baseBlock.onEntityLand(world, entity);
|
||||||
|
@ -86,6 +97,6 @@ public class CloudStairsBlock extends StairsBlock implements CloudLike {
|
||||||
@Override
|
@Override
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public boolean canPathfindThrough(BlockState state, BlockView world, BlockPos pos, NavigationType type) {
|
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,
|
public NaturalCloudBlock(Settings settings, boolean meltable,
|
||||||
@Nullable Supplier<Soakable> soggyBlock,
|
@Nullable Supplier<Soakable> soggyBlock,
|
||||||
Supplier<Block> compactedBlock) {
|
Supplier<Block> compactedBlock) {
|
||||||
super(settings.nonOpaque(), meltable, soggyBlock);
|
super(settings, meltable, soggyBlock);
|
||||||
this.compactedBlock = compactedBlock;
|
this.compactedBlock = compactedBlock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Deprecated
|
||||||
@Override
|
@Override
|
||||||
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
public ActionResult onUse(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||||
ItemStack stack = player.getStackInHand(hand);
|
ItemStack stack = player.getStackInHand(hand);
|
||||||
|
@ -41,6 +42,6 @@ public class NaturalCloudBlock extends PoreousCloudBlock {
|
||||||
return ActionResult.SUCCESS;
|
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 com.minelittlepony.unicopia.block.state.StateUtil;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
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.BlockPos;
|
||||||
import net.minecraft.util.math.random.Random;
|
import net.minecraft.util.math.random.Random;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class PoreousCloudBlock extends CloudBlock implements Soakable {
|
public class PoreousCloudBlock extends CloudBlock implements Soakable {
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -20,6 +25,12 @@ public class PoreousCloudBlock extends CloudBlock implements Soakable {
|
||||||
this.soggyBlock = soggyBlock;
|
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
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockState getStateWithMoisture(BlockState state, int moisture) {
|
public BlockState getStateWithMoisture(BlockState state, int moisture) {
|
||||||
|
|
|
@ -7,6 +7,12 @@ import org.jetbrains.annotations.Nullable;
|
||||||
import com.minelittlepony.unicopia.block.state.StateUtil;
|
import com.minelittlepony.unicopia.block.state.StateUtil;
|
||||||
|
|
||||||
import net.minecraft.block.BlockState;
|
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 {
|
public class PoreousCloudStairsBlock extends CloudStairsBlock implements Soakable {
|
||||||
|
|
||||||
|
@ -17,6 +23,12 @@ public class PoreousCloudStairsBlock extends CloudStairsBlock implements Soakabl
|
||||||
this.soggyBlock = soggyBlock;
|
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
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockState getStateWithMoisture(BlockState state, int moisture) {
|
public BlockState getStateWithMoisture(BlockState state, int moisture) {
|
||||||
|
|
|
@ -9,8 +9,11 @@ import com.minelittlepony.unicopia.USounds;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.ItemUsage;
|
||||||
import net.minecraft.item.Items;
|
import net.minecraft.item.Items;
|
||||||
import net.minecraft.particle.ParticleTypes;
|
import net.minecraft.particle.ParticleTypes;
|
||||||
|
import net.minecraft.potion.PotionUtil;
|
||||||
|
import net.minecraft.potion.Potions;
|
||||||
import net.minecraft.server.world.ServerWorld;
|
import net.minecraft.server.world.ServerWorld;
|
||||||
import net.minecraft.sound.SoundCategory;
|
import net.minecraft.sound.SoundCategory;
|
||||||
import net.minecraft.sound.SoundEvents;
|
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) {
|
static ActionResult tryCollectMoisture(BlockState state, World world, BlockPos pos, PlayerEntity player, Hand hand, BlockHitResult hit) {
|
||||||
if (state.getBlock() instanceof Soakable soakable) {
|
if (state.getBlock() instanceof Soakable soakable) {
|
||||||
ItemStack stack = player.getStackInHand(hand);
|
ItemStack stack = player.getStackInHand(hand);
|
||||||
if (stack.getItem() == Items.GLASS_BOTTLE) {
|
if (stack.isOf(Items.GLASS_BOTTLE)) {
|
||||||
if (!player.isCreative()) {
|
player.setStackInHand(hand, ItemUsage.exchangeStack(stack, player, Items.POTION.getDefaultStack(), false));
|
||||||
stack.split(1);
|
|
||||||
}
|
|
||||||
if (stack.isEmpty()) {
|
|
||||||
player.setStackInHand(hand, Items.POTION.getDefaultStack());
|
|
||||||
} else {
|
|
||||||
player.giveItemStack(Items.POTION.getDefaultStack());
|
|
||||||
}
|
|
||||||
world.playSound(player, player.getX(), player.getY(), player.getZ(), USounds.Vanilla.ITEM_BOTTLE_FILL, SoundCategory.NEUTRAL, 1, 1);
|
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);
|
world.emitGameEvent(player, GameEvent.FLUID_PICKUP, pos);
|
||||||
updateMoisture(soakable, state, world, pos, soakable.getMoisture(state) - 1);
|
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;
|
return ActionResult.PASS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,7 +92,7 @@ public interface Soakable {
|
||||||
if (moisture < 7) {
|
if (moisture < 7) {
|
||||||
world.setBlockState(pos, soakable.getStateWithMoisture(state, moisture + 1));
|
world.setBlockState(pos, soakable.getStateWithMoisture(state, moisture + 1));
|
||||||
}
|
}
|
||||||
} else {
|
} else if (!world.isAir(pos.up())) {
|
||||||
if (moisture > 1) {
|
if (moisture > 1) {
|
||||||
BlockPos neighborPos = pos.offset(Util.getRandom(Soakable.DIRECTIONS, random));
|
BlockPos neighborPos = pos.offset(Util.getRandom(Soakable.DIRECTIONS, random));
|
||||||
BlockState neighborState = world.getBlockState(neighborPos);
|
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.Block;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.state.StateManager;
|
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.util.math.BlockPos;
|
||||||
import net.minecraft.world.BlockView;
|
import net.minecraft.world.BlockView;
|
||||||
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class SoggyCloudStairsBlock extends CloudStairsBlock implements Soakable {
|
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);
|
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
|
@Nullable
|
||||||
@Override
|
@Override
|
||||||
public BlockState getStateWithMoisture(BlockState state, int moisture) {
|
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.block.ItemJarBlock.TileData;
|
||||||
import com.minelittlepony.unicopia.util.FluidHelper;
|
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.FluidConstants;
|
||||||
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
import net.fabricmc.fabric.api.transfer.v1.fluid.FluidVariant;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
import net.minecraft.entity.player.PlayerEntity;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
import net.minecraft.item.Items;
|
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
import net.minecraft.util.TypedActionResult;
|
import net.minecraft.util.TypedActionResult;
|
||||||
|
@ -27,7 +27,7 @@ public record FluidOnlyJarContents (
|
||||||
@Override
|
@Override
|
||||||
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
|
public TypedActionResult<JarContents> interact(PlayerEntity player, Hand hand) {
|
||||||
ItemStack stack = player.getStackInHand(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);
|
long remainder = FluidHelper.deposit(stack, player, hand, fluid, amount);
|
||||||
tile.markDirty();
|
tile.markDirty();
|
||||||
fluid.getFluid().getBucketFillSound().ifPresent(sound -> player.playSound(sound, 1, 1));
|
fluid.getFluid().getBucketFillSound().ifPresent(sound -> player.playSound(sound, 1, 1));
|
||||||
|
|
|
@ -30,15 +30,16 @@ public record ItemsJarContents (
|
||||||
TileData tile,
|
TileData tile,
|
||||||
List<ItemStack> stacks
|
List<ItemStack> stacks
|
||||||
) implements JarContents, SidedInventory {
|
) 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) {
|
public ItemsJarContents(TileData tile) {
|
||||||
this(tile, new ArrayList<>());
|
this(tile, new ArrayList<>(MAX_SIZE));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ItemsJarContents(TileData tile, NbtCompound compound) {
|
public ItemsJarContents(TileData tile, NbtCompound compound) {
|
||||||
this(tile, NbtSerialisable.ITEM_STACK.readAll(compound.getList("items", NbtElement.COMPOUND_TYPE))
|
this(tile, NbtSerialisable.ITEM_STACK.readAll(compound.getList("items", NbtElement.COMPOUND_TYPE))
|
||||||
.limit(15)
|
.limit(MAX_SIZE)
|
||||||
.collect(Collectors.toList()));
|
.collect(Collectors.toList()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +116,7 @@ public record ItemsJarContents (
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public int size() {
|
public int size() {
|
||||||
return 15;
|
return MAX_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -3,9 +3,9 @@ package com.minelittlepony.unicopia.client;
|
||||||
import com.minelittlepony.unicopia.EquinePredicates;
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
|
|
||||||
import net.minecraft.client.MinecraftClient;
|
import net.minecraft.client.MinecraftClient;
|
||||||
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.effect.StatusEffectInstance;
|
import net.minecraft.entity.effect.StatusEffectInstance;
|
||||||
import net.minecraft.entity.effect.StatusEffects;
|
import net.minecraft.entity.effect.StatusEffects;
|
||||||
import net.minecraft.entity.player.PlayerEntity;
|
|
||||||
|
|
||||||
public class BatEyesApplicator {
|
public class BatEyesApplicator {
|
||||||
|
|
||||||
|
@ -15,11 +15,17 @@ public class BatEyesApplicator {
|
||||||
|
|
||||||
private final MinecraftClient client = MinecraftClient.getInstance();
|
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() {
|
public void enable() {
|
||||||
if (client.world != null) {
|
if (client.world != null && client.player != null) {
|
||||||
PlayerEntity player = client.player;
|
if (!client.player.hasStatusEffect(StatusEffects.NIGHT_VISION) && EquinePredicates.PLAYER_BAT.test(client.player)) {
|
||||||
if (!player.hasStatusEffect(StatusEffects.NIGHT_VISION) && EquinePredicates.PLAYER_BAT.test(player)) {
|
client.player.addStatusEffect(new StatusEffectInstance(StatusEffects.NIGHT_VISION, -1, 1, false, false));
|
||||||
player.addStatusEffect(new StatusEffectInstance(StatusEffects.NIGHT_VISION, 1, 1, false, false));
|
|
||||||
batEyesApplied = true;
|
batEyesApplied = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,6 @@ import com.minelittlepony.unicopia.container.*;
|
||||||
import com.minelittlepony.unicopia.entity.player.PlayerCamera;
|
import com.minelittlepony.unicopia.entity.player.PlayerCamera;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.minelittlepony.unicopia.network.handler.ClientNetworkHandlerImpl;
|
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.server.world.ZapAppleStageStore;
|
||||||
import com.minelittlepony.unicopia.util.Lerp;
|
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.entity.player.PlayerEntity;
|
||||||
import net.minecraft.resource.ResourceType;
|
import net.minecraft.resource.ResourceType;
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.math.BlockPos;
|
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
|
@ -55,10 +53,6 @@ public class UnicopiaClient implements ClientModInitializer {
|
||||||
return Pony.of(MinecraftClient.getInstance().player);
|
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 tangentalSkyAngle = new Lerp(0, true);
|
||||||
public final Lerp skyAngle = 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();
|
return Unicopia.getConfig().preferredRace.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
public static float getWorldBrightness(float initial) {
|
|
||||||
return 0.6F;
|
|
||||||
}
|
|
||||||
|
|
||||||
public UnicopiaClient() {
|
public UnicopiaClient() {
|
||||||
instance = this;
|
instance = this;
|
||||||
}
|
}
|
||||||
|
@ -157,38 +147,22 @@ public class UnicopiaClient implements ClientModInitializer {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onWorldTick(ClientWorld world) {
|
private void onWorldTick(ClientWorld world) {
|
||||||
BlockPos pos = MinecraftClient.getInstance().getCameraEntity().getBlockPos();
|
/*BlockPos pos = MinecraftClient.getInstance().getCameraEntity().getBlockPos();
|
||||||
float tickDelta = MinecraftClient.getInstance().getTickDelta();
|
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) {
|
((WeatherAccess)world).setWeatherOverride(null, null);
|
||||||
rainGradient.update(targetRainGradient, 2000);
|
rainGradient.update(targetRainGradient == null ? world.getRainGradient(tickDelta) : targetRainGradient, 2000);
|
||||||
}
|
|
||||||
|
|
||||||
float gradient = rainGradient.getValue();
|
((WeatherAccess)world).setWeatherOverride(1F, null);
|
||||||
if (!rainGradient.isFinished()) {
|
thunderGradient.update(targetThunderGradient == null ? world.getThunderGradient(tickDelta) : targetThunderGradient, 2000);
|
||||||
world.setRainGradient(gradient);
|
|
||||||
world.setThunderGradient(gradient);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private Float getTargetRainGradient(ClientWorld world, BlockPos pos, float tickDelta) {
|
((WeatherAccess)world).setWeatherOverride(
|
||||||
if (WeatherConditions.get(world).isInRangeOfStorm(pos)) {
|
rainGradient.isFinished() ? targetRainGradient : (Float)rainGradient.getValue(),
|
||||||
if (originalRainGradient == null) {
|
thunderGradient.isFinished() ? targetThunderGradient : (Float)thunderGradient.getValue()
|
||||||
originalRainGradient = world.getRainGradient(tickDelta);
|
);*/
|
||||||
}
|
|
||||||
|
|
||||||
return 1F;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (originalRainGradient != null) {
|
|
||||||
Float f = originalRainGradient;
|
|
||||||
originalRainGradient = null;
|
|
||||||
return f;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void onScreenInit(Screen screen, ButtonList buttons) {
|
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.gui.DrawContext;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
import net.minecraft.client.util.math.MatrixStack;
|
||||||
import net.minecraft.text.MutableText;
|
import net.minecraft.text.MutableText;
|
||||||
|
import net.minecraft.util.Colors;
|
||||||
import net.minecraft.util.Formatting;
|
import net.minecraft.util.Formatting;
|
||||||
import net.minecraft.util.math.MathHelper;
|
import net.minecraft.util.math.MathHelper;
|
||||||
|
|
||||||
|
@ -145,10 +146,7 @@ class Slot {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
MutableText label = KeyBindingsHandler.INSTANCE.getBinding(aSlot).getLabel().copy().formatted(Formatting.BOLD);
|
MutableText label = KeyBindingsHandler.INSTANCE.getBinding(aSlot).getLabel().copy();
|
||||||
|
|
||||||
MatrixStack matrices = context.getMatrices();
|
|
||||||
matrices.push();
|
|
||||||
|
|
||||||
int x = getX();
|
int x = getX();
|
||||||
if (uHud.xDirection > 0) {
|
if (uHud.xDirection > 0) {
|
||||||
|
@ -158,9 +156,6 @@ class Slot {
|
||||||
x -= uHud.client.textRenderer.getWidth(label)/2;
|
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();
|
ActivationType activation = KeyBindingsHandler.INSTANCE.getForcedActivationType();
|
||||||
if (activation.isResult()) {
|
if (activation.isResult()) {
|
||||||
label = label.append("+T" + activation.getTapCount());
|
label = label.append("+T" + activation.getTapCount());
|
||||||
|
@ -169,8 +164,6 @@ class Slot {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
context.drawText(uHud.font, label, 0, 0, 0xFFFFFF, true);
|
DrawableUtil.drawScaledText(context, label, x, getY() + labelY, 0.5F, Colors.WHITE);
|
||||||
|
|
||||||
matrices.pop();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -104,10 +104,12 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
public void render(DrawContext context, int mouseX, int mouseY, float delta) {
|
||||||
|
context.getMatrices().push();
|
||||||
|
context.getMatrices().translate(0, 0, -2);
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
context.getMatrices().push();
|
context.getMatrices().push();
|
||||||
context.getMatrices().translate(0, 0, -100);
|
context.getMatrices().translate(0, 0, -100);
|
||||||
parent.render(context, 0, 0, delta);
|
parent.render(context, -1, -1, delta);
|
||||||
context.getMatrices().pop();
|
context.getMatrices().pop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -119,30 +121,20 @@ public class TribeConfirmationScreen extends GameGui implements HidesHud {
|
||||||
int left = (width - columnWidth) / 2;
|
int left = (width - columnWidth) / 2;
|
||||||
|
|
||||||
top += 40;
|
top += 40;
|
||||||
|
|
||||||
final int zOffset = 0;
|
final int zOffset = 0;
|
||||||
|
|
||||||
context.drawTexture(TribeSelectionScreen.TEXTURE, left + zOffset, top, 0, 70, 123, columnHeight);
|
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, left + segmentWidth + zOffset, top, 20, 70, 123, columnHeight);
|
||||||
|
context.drawTexture(TribeSelectionScreen.TEXTURE, width - left - segmentWidth + zOffset + 1, top, 10, 70, 123, columnHeight);
|
||||||
context.drawTexture(TribeSelectionScreen.TEXTURE, width - left - segmentWidth + zOffset, top, 10, 70, 123, columnHeight);
|
|
||||||
|
|
||||||
top -= 31;
|
top -= 31;
|
||||||
|
|
||||||
left = width / 2;
|
left = width / 2;
|
||||||
|
|
||||||
context.drawTexture(TribeSelectionScreen.TEXTURE, left - 55, top, 140, 70, 21, 50);
|
context.drawTexture(TribeSelectionScreen.TEXTURE, left - 55, top, 140, 70, 21, 50);
|
||||||
context.drawTexture(TribeSelectionScreen.TEXTURE, left + 35, top, 148, 70, 21, 50);
|
context.drawTexture(TribeSelectionScreen.TEXTURE, left + 35, top, 148, 70, 21, 50);
|
||||||
|
|
||||||
textBody.render(context, mouseX, mouseY, delta);
|
textBody.render(context, mouseX, mouseY, delta);
|
||||||
|
context.getMatrices().pop();
|
||||||
context.getMatrices().push();
|
|
||||||
context.getMatrices().translate(0, 0, 2);
|
|
||||||
context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 5, 10, 70, 69, 50);
|
context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 5, 10, 70, 69, 50);
|
||||||
context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 15, 10, 70, 69, 50);
|
context.drawTexture(TribeSelectionScreen.TEXTURE, left - 35, top - 15, 10, 70, 69, 50);
|
||||||
super.render(context, mouseX, mouseY, delta);
|
super.render(context, mouseX, mouseY, delta);
|
||||||
context.getMatrices().pop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -51,8 +51,8 @@ public class UHud {
|
||||||
|
|
||||||
private final List<Slot> slots = List.of(
|
private final List<Slot> slots = List.of(
|
||||||
new ManaRingSlot(this, AbilitySlot.PRIMARY, AbilitySlot.PASSIVE, 0, 0),
|
new ManaRingSlot(this, AbilitySlot.PRIMARY, AbilitySlot.PASSIVE, 0, 0),
|
||||||
new Slot(this, AbilitySlot.SECONDARY, AbilitySlot.SECONDARY, 30, -8),
|
new Slot(this, AbilitySlot.SECONDARY, AbilitySlot.SECONDARY, 30, -10),
|
||||||
new Slot(this, AbilitySlot.TERTIARY, AbilitySlot.TERTIARY, 40, 18)
|
new Slot(this, AbilitySlot.TERTIARY, AbilitySlot.TERTIARY, 43, 10)
|
||||||
);
|
);
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
|
@ -84,7 +84,7 @@ public class UHud {
|
||||||
Pony pony = Pony.of(client.player);
|
Pony pony = Pony.of(client.player);
|
||||||
|
|
||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.translate(0, 0, hotbarZ);
|
matrices.translate(0, 0, hotbarZ - 9800);
|
||||||
renderViewEffects(pony, context, scaledWidth, scaledHeight, tickDelta);
|
renderViewEffects(pony, context, scaledWidth, scaledHeight, tickDelta);
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
|
|
||||||
|
@ -137,9 +137,11 @@ public class UHud {
|
||||||
|
|
||||||
slots.forEach(slot -> slot.renderBackground(context, abilities, swap, tickDelta));
|
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)
|
Ability<?> ability = pony.getAbilities().getStat(AbilitySlot.PRIMARY)
|
||||||
.getAbility(Unicopia.getConfig().hudPage.get())
|
.getAbility(currentPage)
|
||||||
.orElse(null);
|
.orElse(null);
|
||||||
boolean canCast = ability == Abilities.CAST || ability == Abilities.KIRIN_CAST || ability == Abilities.SHOOT;
|
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));
|
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();
|
matrices.pop();
|
||||||
|
|
||||||
if (canCast) {
|
if (canCast) {
|
||||||
|
@ -188,7 +198,7 @@ public class UHud {
|
||||||
int progress = Math.min(255, (int)(time * 255F / 20F));
|
int progress = Math.min(255, (int)(time * 255F / 20F));
|
||||||
|
|
||||||
if (progress > 8) {
|
if (progress > 8) {
|
||||||
int color = 0xFFFFFF;
|
int color = Colors.WHITE;
|
||||||
int alpha = progress << 24 & -16777216;
|
int alpha = progress << 24 & -16777216;
|
||||||
|
|
||||||
color |= alpha;
|
color |= alpha;
|
||||||
|
|
|
@ -116,7 +116,9 @@ public class Main extends MineLPDelegate implements ClientModInitializer {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public float getPonyHeight(Entity entity) {
|
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) {
|
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);
|
VertexConsumer consumer = ItemRenderer.getArmorGlintConsumer(renderContext, RenderLayer.getArmorCutoutNoCull(texture), false, false);
|
||||||
|
|
||||||
|
if (context.getModel() instanceof BipedEntityModel) {
|
||||||
model.setAngles(entity, context.getModel());
|
model.setAngles(entity, context.getModel());
|
||||||
|
}
|
||||||
model.render(matrices, consumer, lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
|
model.render(matrices, consumer, lightUv, OverlayTexture.DEFAULT_UV, 1, 1, 1, 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -67,10 +67,6 @@ class EntityReplacementManager implements Disguise {
|
||||||
return disguise;
|
return disguise;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public void setDirty() {
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean isDead() {
|
public boolean isDead() {
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -9,7 +9,6 @@ import com.google.common.collect.*;
|
||||||
import com.google.gson.JsonSyntaxException;
|
import com.google.gson.JsonSyntaxException;
|
||||||
import com.minelittlepony.unicopia.Unicopia;
|
import com.minelittlepony.unicopia.Unicopia;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.mojang.blaze3d.systems.RenderSystem;
|
|
||||||
import com.mojang.logging.LogUtils;
|
import com.mojang.logging.LogUtils;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.objects.Object2FloatMap;
|
import it.unimi.dsi.fastutil.objects.Object2FloatMap;
|
||||||
|
@ -52,11 +51,7 @@ public class ViewportShader implements SynchronousResourceReloader, Identifiable
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shaderId == null) {
|
if (shaderId == null || Unicopia.getConfig().disableShaders.get()) {
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Unicopia.getConfig().disableShaders.get()) {
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -81,13 +76,10 @@ public class ViewportShader implements SynchronousResourceReloader, Identifiable
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shader != null && client.player != null) {
|
if (shader != null && client.player != null) {
|
||||||
RenderSystem.disableBlend();
|
|
||||||
RenderSystem.disableDepthTest();
|
|
||||||
RenderSystem.resetTextureMatrix();
|
|
||||||
|
|
||||||
Pony pony = Pony.of(client.player);
|
Pony pony = Pony.of(client.player);
|
||||||
|
|
||||||
float corruption = pony.getCorruption().getScaled(0.9F);
|
float corruption = pony.getCorruption().getScaled(0.9F);
|
||||||
|
if (!MathHelper.approximatelyEquals(corruption, 0)) {
|
||||||
corruption = pony.getInterpolator().interpolate("corruption", corruption, 10);
|
corruption = pony.getInterpolator().interpolate("corruption", corruption, 10);
|
||||||
|
|
||||||
corruption = 1 - corruption + 0.05F;
|
corruption = 1 - corruption + 0.05F;
|
||||||
|
@ -96,14 +88,11 @@ public class ViewportShader implements SynchronousResourceReloader, Identifiable
|
||||||
shader.render(tickDelta);
|
shader.render(tickDelta);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void reload(ResourceManager var1) {
|
public void reload(ResourceManager var1) {
|
||||||
if (shader != null) {
|
loadShader(shader != null ? shader.id : DESATURATION_SHADER);
|
||||||
loadShader(shader.id);
|
|
||||||
} else {
|
|
||||||
loadShader(DESATURATION_SHADER);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static class LoadedShader extends PostEffectProcessor {
|
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);
|
super.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
|
||||||
|
|
||||||
matrices.push();
|
matrices.push();
|
||||||
double height = caster.asEntity().getEyeY() - caster.getOriginVector().y;
|
double height = caster.asEntity().getEyeY() - caster.getOriginVector().getY();
|
||||||
matrices.translate(0, height * 0.5F, 0);
|
|
||||||
|
|
||||||
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();
|
Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity();
|
||||||
|
|
||||||
matrices.push();
|
matrices.push();
|
||||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-45));
|
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
|
||||||
matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(45 + cameraEntity.getYaw(tickDelta)));
|
matrices.multiply(RotationAxis.NEGATIVE_Z.rotationDegrees(cameraEntity.getYaw(tickDelta) - 25));
|
||||||
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-cameraEntity.getPitch(tickDelta)));
|
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);
|
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();
|
matrices.pop();
|
||||||
|
|
|
@ -1,5 +1,7 @@
|
||||||
package com.minelittlepony.unicopia.client.render.spell;
|
package com.minelittlepony.unicopia.client.render.spell;
|
||||||
|
|
||||||
|
import org.joml.Quaternionf;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquinePredicates;
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
import com.minelittlepony.unicopia.ability.magic.Caster;
|
import com.minelittlepony.unicopia.ability.magic.Caster;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
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.VertexConsumerProvider;
|
||||||
import net.minecraft.client.render.model.json.ModelTransformationMode;
|
import net.minecraft.client.render.model.json.ModelTransformationMode;
|
||||||
import net.minecraft.client.util.math.MatrixStack;
|
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.MathHelper;
|
||||||
import net.minecraft.util.math.RotationAxis;
|
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) {
|
private void renderGemstone(MatrixStack matrices, VertexConsumerProvider vertices, T spell, Caster<?> caster, int light, float tickDelta, float animationProgress) {
|
||||||
matrices.push();
|
matrices.push();
|
||||||
|
float scale = 1/8F;
|
||||||
|
matrices.scale(scale, scale, scale);
|
||||||
|
|
||||||
transformGemstone(matrices, vertices, spell, caster, animationProgress);
|
transformGemstone(matrices, vertices, spell, caster, animationProgress);
|
||||||
matrices.push();
|
matrices.push();
|
||||||
|
@ -46,6 +52,22 @@ public class SpellRenderer<T extends Spell> {
|
||||||
matrices.pop();
|
matrices.pop();
|
||||||
|
|
||||||
if (spell instanceof TimedSpell timed) {
|
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);
|
renderCountdown(matrices, timed, tickDelta);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -53,7 +75,7 @@ public class SpellRenderer<T extends Spell> {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void renderCountdown(MatrixStack matrices, TimedSpell spell, float tickDelta) {
|
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 radius = 0.6F;
|
||||||
float timeRemaining = spell.getTimer().getPercentTimeRemaining(tickDelta);
|
float timeRemaining = spell.getTimer().getPercentTimeRemaining(tickDelta);
|
||||||
|
|
||||||
|
@ -67,6 +89,6 @@ public class SpellRenderer<T extends Spell> {
|
||||||
if (caster.asEntity() instanceof CastSpellEntity) {
|
if (caster.asEntity() instanceof CastSpellEntity) {
|
||||||
y = 1F;
|
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.registry.RegistryWrapper;
|
||||||
import net.minecraft.server.command.CommandManager;
|
import net.minecraft.server.command.CommandManager;
|
||||||
import net.minecraft.server.command.ServerCommandSource;
|
import net.minecraft.server.command.ServerCommandSource;
|
||||||
import net.minecraft.server.network.ServerPlayerEntity;
|
|
||||||
import net.minecraft.text.Text;
|
import net.minecraft.text.Text;
|
||||||
import net.minecraft.util.Identifier;
|
import net.minecraft.util.Identifier;
|
||||||
|
|
||||||
|
@ -63,10 +62,8 @@ public class ConfigCommand {
|
||||||
})))
|
})))
|
||||||
)
|
)
|
||||||
.then(CommandManager.literal("list").executes(source -> ConfigCommand.<Set<String>>getProperty(configName, values -> {
|
.then(CommandManager.literal("list").executes(source -> ConfigCommand.<Set<String>>getProperty(configName, values -> {
|
||||||
ServerPlayerEntity player = source.getSource().getPlayerOrThrow();
|
source.getSource().sendFeedback(() -> Text.translatable("command.unicopia.config.list", configName, values.size()), false);
|
||||||
|
values.forEach(line -> source.getSource().sendFeedback(() -> Text.literal(line), false));
|
||||||
player.sendMessage(Text.translatable("command.unicopia.config.list", configName, values.size()), false);
|
|
||||||
values.forEach(line -> player.sendMessage(Text.literal(line)));
|
|
||||||
}))
|
}))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
|
@ -4,8 +4,10 @@ import java.util.function.Function;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquinePredicates;
|
import com.minelittlepony.unicopia.EquinePredicates;
|
||||||
import com.minelittlepony.unicopia.InteractionManager;
|
import com.minelittlepony.unicopia.InteractionManager;
|
||||||
|
import com.minelittlepony.unicopia.ability.Abilities;
|
||||||
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
import com.minelittlepony.unicopia.ability.magic.SpellPredicate;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod;
|
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.ability.magic.spell.effect.SpellType;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
|
@ -81,7 +83,13 @@ public class DisguiseCommand {
|
||||||
|
|
||||||
Pony iplayer = Pony.of(player);
|
Pony iplayer = Pony.of(player);
|
||||||
iplayer.getSpellSlot().get(SpellType.CHANGELING_DISGUISE)
|
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);
|
.setDisguise(entity);
|
||||||
|
|
||||||
if (source.getEntity() == player) {
|
if (source.getEntity() == player) {
|
||||||
|
|
|
@ -50,17 +50,19 @@ class GravityCommand {
|
||||||
l.getPhysics().setBaseGravityModifier(gravity);
|
l.getPhysics().setBaseGravityModifier(gravity);
|
||||||
if (l.asEntity() instanceof PlayerEntity player) {
|
if (l.asEntity() instanceof PlayerEntity player) {
|
||||||
if (source.getEntity() == player) {
|
if (source.getEntity() == player) {
|
||||||
player.sendMessage(Text.translatable("commands.gravity.set.self", gravity));
|
source.sendFeedback(() -> Text.translatable("commands.gravity.set.self", gravity), true);
|
||||||
} else if (source.getWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) {
|
} else {
|
||||||
player.sendMessage(Text.translatable("commands.gravity.set.other", l.asEntity().getDisplayName(), gravity));
|
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();
|
return (Entity)l.asEntity();
|
||||||
}).toList();
|
}).toList();
|
||||||
|
|
||||||
if (affected.size() == 1) {
|
if (affected.size() > 1) {
|
||||||
source.sendFeedback(() -> Text.translatable("commands.gravity.set.other", affected.get(0).getDisplayName()), true);
|
|
||||||
} else {
|
|
||||||
source.sendFeedback(() -> Text.translatable("commands.gravity.set.multiple", affected.size()), true);
|
source.sendFeedback(() -> Text.translatable("commands.gravity.set.multiple", affected.size()), true);
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -24,7 +24,7 @@ public class ManaCommand {
|
||||||
var pony = Pony.of(source.getSource().getPlayer());
|
var pony = Pony.of(source.getSource().getPlayer());
|
||||||
var bar = type.getBar(pony.getMagicalReserves());
|
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;
|
return 0;
|
||||||
})
|
})
|
||||||
.then(CommandManager.argument("value", FloatArgumentType.floatArg()).executes(source -> {
|
.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);
|
pony.asWorld().playSound(null, pony.getOrigin(), USounds.Vanilla.ENTITY_PLAYER_LEVELUP, SoundCategory.PLAYERS, 1, 2);
|
||||||
}
|
}
|
||||||
bar.set(value);
|
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;
|
return 0;
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,10 +44,10 @@ class SpeciesCommand {
|
||||||
))
|
))
|
||||||
.then(CommandManager.literal("describe")
|
.then(CommandManager.literal("describe")
|
||||||
.then(CommandManager.argument("race", Race.argument()).suggests(UCommandSuggestion.ALL_RACE_SUGGESTIONS)
|
.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")
|
.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);
|
source.sendFeedback(() -> Text.translatable("commands.race.success.other", player.getName(), race.getDisplayName()), true);
|
||||||
}
|
}
|
||||||
} else if (player.getEntityWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) {
|
} else {
|
||||||
player.sendMessage(Text.translatable("commands.race.permission"), false);
|
source.sendFeedback(() -> Text.translatable("commands.race.permission"), false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int get(ServerCommandSource source, PlayerEntity player, boolean isSelf) {
|
static int get(ServerCommandSource source, PlayerEntity player, boolean isSelf) {
|
||||||
|
source.sendFeedback(() -> {
|
||||||
Race spec = Pony.of(player).getSpecies();
|
Race spec = Pony.of(player).getSpecies();
|
||||||
|
|
||||||
String name = "commands.race.tell.";
|
String name = "commands.race.tell.";
|
||||||
name += isSelf ? "self" : "other";
|
name += isSelf ? "self" : "other";
|
||||||
|
|
||||||
player.sendMessage(Text.translatable(name, player.getName())
|
return Text.translatable(name, player.getName())
|
||||||
.append(Text.translatable(spec.getTranslationKey())
|
.append(Text.translatable(spec.getTranslationKey())
|
||||||
.styled(s -> s.withColor(Formatting.GOLD))), false);
|
.styled(s -> s.withColor(Formatting.GOLD)));
|
||||||
|
}, false);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int list(PlayerEntity player) {
|
static int list(ServerCommandSource source) {
|
||||||
player.sendMessage(Text.translatable("commands.race.list"), false);
|
source.sendFeedback(() -> Text.translatable("commands.race.list"), false);
|
||||||
|
source.sendFeedback(() -> {
|
||||||
MutableText message = Text.literal("");
|
MutableText message = Text.literal("");
|
||||||
|
|
||||||
boolean first = true;
|
boolean first = true;
|
||||||
for (Race i : Race.REGISTRY) {
|
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(Text.literal((!first ? "\n" : "") + " - "));
|
||||||
message.append(i.getDisplayName());
|
message.append(i.getDisplayName());
|
||||||
first = false;
|
first = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
player.sendMessage(message.styled(s -> s.withColor(Formatting.GOLD)), false);
|
return message.styled(s -> s.withColor(Formatting.GOLD));
|
||||||
|
}, false);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int describe(PlayerEntity player, Race species) {
|
static int describe(ServerCommandSource source, Race species) {
|
||||||
Identifier id = Race.REGISTRY.getId(species);
|
Identifier id = Race.REGISTRY.getId(species);
|
||||||
|
|
||||||
for (String category : new String[] { "goods", "bads" }) {
|
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),
|
String.format("gui.unicopia.tribe_selection.confirm.%s.%d.%s.%s", category),
|
||||||
species.getAltDisplayName()
|
species.getAltDisplayName()
|
||||||
), false);
|
), false);
|
||||||
for (int i = 1; i < 5; i++) {
|
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());
|
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.server.command.ServerCommandSource;
|
||||||
import net.minecraft.text.*;
|
import net.minecraft.text.*;
|
||||||
import net.minecraft.util.Hand;
|
import net.minecraft.util.Hand;
|
||||||
|
import net.minecraft.world.GameRules;
|
||||||
|
|
||||||
class TraitCommand {
|
class TraitCommand {
|
||||||
static LiteralArgumentBuilder<ServerCommandSource> create() {
|
static LiteralArgumentBuilder<ServerCommandSource> create() {
|
||||||
|
@ -78,7 +79,9 @@ class TraitCommand {
|
||||||
float gravity = iplayer.getPhysics().getGravityModifier();
|
float gravity = iplayer.getPhysics().getGravityModifier();
|
||||||
|
|
||||||
if (source.getPlayer() == player) {
|
if (source.getPlayer() == player) {
|
||||||
|
if (player.getEntityWorld().getGameRules().getBoolean(GameRules.SEND_COMMAND_FEEDBACK)) {
|
||||||
player.sendMessage(Text.translatable(translationKey, gravity), false);
|
player.sendMessage(Text.translatable(translationKey, gravity), false);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
source.sendFeedback(() -> Text.translatable(translationKey + ".other", player.getName(), gravity), true);
|
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) {
|
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) {
|
EquippedStack(LivingEntity entity, EquipmentSlot slot) {
|
||||||
this(entity.getEquippedStack(slot), () -> {}, l -> l.sendEquipmentBreakStatus(slot));
|
this(entity.getEquippedStack(slot), () -> {}, l -> l.sendEquipmentBreakStatus(slot));
|
||||||
|
|
|
@ -148,12 +148,14 @@ public class DietProfileGenerator {
|
||||||
bakedGoodExtremePreference, pineconeMultiplier, properMeatStandards, seaFoodExclusions,
|
bakedGoodExtremePreference, pineconeMultiplier, properMeatStandards, seaFoodExclusions,
|
||||||
// They have a sweet tooth
|
// 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("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("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("insect/cooked")).hunger(0.1F).saturation(0.1F).build(),
|
||||||
new Multiplier.Builder().tag(Unicopia.id("meat/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(
|
), List.of(
|
||||||
// Candy and rocks gives them a massive saturation boost. Maybe too much?
|
// 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("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()
|
new FoodGroupEffects.Builder().tag(Unicopia.id("desserts")).food(UFoodComponents.builder(12, 32).snack().alwaysEdible()).build()
|
||||||
), Optional.empty()));
|
), Optional.empty()));
|
||||||
// Pegasi prefer fish over other food sources
|
// 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("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("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("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("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("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(
|
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.Unicopia;
|
||||||
import com.minelittlepony.unicopia.block.UBlocks;
|
import com.minelittlepony.unicopia.block.UBlocks;
|
||||||
import com.minelittlepony.unicopia.server.world.Tree;
|
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.FabricDataOutput;
|
||||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
|
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")));
|
).forceAddTag(TagKey.of(RegistryKeys.BLOCK, new Identifier("c", "concrete_powders")));
|
||||||
|
|
||||||
getOrCreateTagBuilder(UTags.Blocks.UNAFFECTED_BY_GROW_ABILITY).add(Blocks.GRASS_BLOCK);
|
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() {
|
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.FabricDataOutput;
|
||||||
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
|
import net.fabricmc.fabric.api.datagen.v1.provider.FabricTagProvider;
|
||||||
import net.minecraft.entity.damage.DamageType;
|
import net.minecraft.entity.damage.DamageType;
|
||||||
|
import net.minecraft.entity.damage.DamageTypes;
|
||||||
import net.minecraft.registry.RegistryKeys;
|
import net.minecraft.registry.RegistryKeys;
|
||||||
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
|
import net.minecraft.registry.RegistryWrapper.WrapperLookup;
|
||||||
import net.minecraft.registry.tag.DamageTypeTags;
|
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);
|
).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_ROCKS).add(UDamageTypes.ROCK);
|
||||||
getOrCreateTagBuilder(UTags.DamageTypes.FROM_HORSESHOES).add(UDamageTypes.HORSESHOE);
|
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(
|
getOrCreateTagBuilder(DamageTypeTags.AVOIDS_GUARDIAN_THORNS).add(
|
||||||
UDamageTypes.EXHAUSTION, UDamageTypes.ALICORN_AMULET, UDamageTypes.ZAP_APPLE, UDamageTypes.KICK, UDamageTypes.SMASH,
|
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.EXHAUSTION, UDamageTypes.GAVITY_WELL_RECOIL, UDamageTypes.ALICORN_AMULET,
|
||||||
UDamageTypes.ZAP_APPLE, UDamageTypes.KICK, UDamageTypes.SMASH, UDamageTypes.BAT_SCREECH,
|
UDamageTypes.ZAP_APPLE, UDamageTypes.KICK, UDamageTypes.SMASH, UDamageTypes.BAT_SCREECH,
|
||||||
UDamageTypes.LOVE_DRAINING, UDamageTypes.LIFE_DRAINING, UDamageTypes.STEAMROLLER, UDamageTypes.RAINBOOM,
|
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_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(
|
getOrCreateTagBuilder(DamageTypeTags.BYPASSES_SHIELD).add(
|
||||||
UDamageTypes.EXHAUSTION, UDamageTypes.BAT_SCREECH, UDamageTypes.ALICORN_AMULET,
|
UDamageTypes.EXHAUSTION, UDamageTypes.BAT_SCREECH, UDamageTypes.ALICORN_AMULET,
|
||||||
UDamageTypes.LOVE_DRAINING, UDamageTypes.LIFE_DRAINING,
|
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_STAIRS, UTags.Items.CLOUD_STAIRS);
|
||||||
copy(UTags.Blocks.CLOUD_BLOCKS, UTags.Items.CLOUD_BLOCKS);
|
copy(UTags.Blocks.CLOUD_BLOCKS, UTags.Items.CLOUD_BLOCKS);
|
||||||
copy(UTags.Blocks.CHITIN_BLOCKS, UTags.Items.CHITIN_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() {
|
private void exportForagingTags() {
|
||||||
|
@ -348,6 +353,7 @@ public class UItemTagProvider extends FabricTagProvider.ItemTagProvider {
|
||||||
getOrCreateTagBuilder(UConventionalTags.Items.WORMS).add(UItems.WHEAT_WORMS);
|
getOrCreateTagBuilder(UConventionalTags.Items.WORMS).add(UItems.WHEAT_WORMS);
|
||||||
getOrCreateTagBuilder(UConventionalTags.Items.STICKS).add(Items.STICK);
|
getOrCreateTagBuilder(UConventionalTags.Items.STICKS).add(Items.STICK);
|
||||||
getOrCreateTagBuilder(UConventionalTags.Items.ROCKS).add(UItems.ROCK);
|
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.PINECONES).add(UItems.PINECONE);
|
||||||
getOrCreateTagBuilder(UConventionalTags.Items.PINEAPPLES).add(UItems.PINEAPPLE);
|
getOrCreateTagBuilder(UConventionalTags.Items.PINEAPPLES).add(UItems.PINEAPPLE);
|
||||||
getOrCreateTagBuilder(UConventionalTags.Items.MANGOES).add(UItems.MANGO);
|
getOrCreateTagBuilder(UConventionalTags.Items.MANGOES).add(UItems.MANGO);
|
||||||
|
|
|
@ -26,7 +26,7 @@ public interface AttributeContainer {
|
||||||
EntityAttributeModifier modifier = instance.getModifier(id);
|
EntityAttributeModifier modifier = instance.getModifier(id);
|
||||||
|
|
||||||
if (!MathHelper.approximatelyEquals(desiredValue, modifier == null ? 0 : modifier.getValue())) {
|
if (!MathHelper.approximatelyEquals(desiredValue, modifier == null ? 0 : modifier.getValue())) {
|
||||||
instance.tryRemoveModifier(id);
|
instance.removeModifier(id);
|
||||||
|
|
||||||
if (desiredValue != 0) {
|
if (desiredValue != 0) {
|
||||||
if (permanent) {
|
if (permanent) {
|
||||||
|
|
|
@ -11,7 +11,6 @@ import com.minelittlepony.unicopia.InteractionManager;
|
||||||
import com.minelittlepony.unicopia.Race;
|
import com.minelittlepony.unicopia.Race;
|
||||||
import com.minelittlepony.unicopia.WeaklyOwned;
|
import com.minelittlepony.unicopia.WeaklyOwned;
|
||||||
import com.minelittlepony.unicopia.ability.magic.*;
|
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.ability.magic.spell.effect.TargetSelecter;
|
||||||
import com.minelittlepony.unicopia.entity.ai.BreakHeartGoal;
|
import com.minelittlepony.unicopia.entity.ai.BreakHeartGoal;
|
||||||
import com.minelittlepony.unicopia.entity.ai.DynamicTargetGoal;
|
import com.minelittlepony.unicopia.entity.ai.DynamicTargetGoal;
|
||||||
|
@ -302,9 +301,6 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
||||||
@Override
|
@Override
|
||||||
public void toNBT(NbtCompound compound) {
|
public void toNBT(NbtCompound compound) {
|
||||||
super.toNBT(compound);
|
super.toNBT(compound);
|
||||||
getSpellSlot().get().ifPresent(effect -> {
|
|
||||||
compound.put("effect", Spell.writeNbt(effect));
|
|
||||||
});
|
|
||||||
compound.put("master", getMasterReference().toNBT());
|
compound.put("master", getMasterReference().toNBT());
|
||||||
physics.toNBT(compound);
|
physics.toNBT(compound);
|
||||||
compound.putBoolean("discorded", isDiscorded());
|
compound.putBoolean("discorded", isDiscorded());
|
||||||
|
@ -313,9 +309,6 @@ public class Creature extends Living<LivingEntity> implements WeaklyOwned.Mutabl
|
||||||
@Override
|
@Override
|
||||||
public void fromNBT(NbtCompound compound) {
|
public void fromNBT(NbtCompound compound) {
|
||||||
super.fromNBT(compound);
|
super.fromNBT(compound);
|
||||||
if (compound.contains("effect")) {
|
|
||||||
getSpellSlot().put(Spell.readNbt(compound.getCompound("effect")));
|
|
||||||
}
|
|
||||||
if (compound.contains("master", NbtElement.COMPOUND_TYPE)) {
|
if (compound.contains("master", NbtElement.COMPOUND_TYPE)) {
|
||||||
owner.fromNBT(compound.getCompound("master"));
|
owner.fromNBT(compound.getCompound("master"));
|
||||||
if (owner.isSet()) {
|
if (owner.isSet()) {
|
||||||
|
|
|
@ -10,12 +10,12 @@ import com.minelittlepony.unicopia.util.Tickable;
|
||||||
import net.minecraft.block.BlockState;
|
import net.minecraft.block.BlockState;
|
||||||
import net.minecraft.block.FenceGateBlock;
|
import net.minecraft.block.FenceGateBlock;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.entity.EntityPose;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.mob.MobEntity;
|
import net.minecraft.entity.mob.MobEntity;
|
||||||
import net.minecraft.nbt.NbtCompound;
|
import net.minecraft.nbt.NbtCompound;
|
||||||
import net.minecraft.registry.tag.BlockTags;
|
import net.minecraft.registry.tag.BlockTags;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.MathHelper;
|
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
|
|
||||||
public class EntityPhysics<T extends Entity> implements Physics, Copyable<EntityPhysics<T>>, Tickable {
|
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
|
@Override
|
||||||
public BlockPos getHeadPosition() {
|
public BlockPos getHeadPosition() {
|
||||||
|
BlockPos pos = BlockPos.ofFloored(
|
||||||
BlockPos pos = new BlockPos(
|
entity.getX(),
|
||||||
MathHelper.floor(entity.getX()),
|
entity.getY() + entity.getEyeHeight(EntityPose.STANDING),
|
||||||
MathHelper.floor(entity.getY() + entity.getHeight() + 0.20000000298023224D),
|
entity.getZ()
|
||||||
MathHelper.floor(entity.getZ())
|
|
||||||
);
|
);
|
||||||
|
|
||||||
if (entity.getWorld().getBlockState(pos).isAir()) {
|
if (entity.getWorld().getBlockState(pos).isAir()) {
|
||||||
BlockPos below = pos.down();
|
BlockPos below = pos.down();
|
||||||
BlockState block = entity.getWorld().getBlockState(below);
|
BlockState block = entity.getWorld().getBlockState(below);
|
||||||
if (block.isIn(BlockTags.FENCES) || block.isIn(BlockTags.WALLS) || block.getBlock() instanceof FenceGateBlock) {
|
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);
|
CorruptInfluenceStatusEffect.reproduce(mob);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,7 @@ public class BreakHeartGoal extends Goal {
|
||||||
public void stop() {
|
public void stop() {
|
||||||
targetter.stop();
|
targetter.stop();
|
||||||
mob.getNavigation().stop();
|
mob.getNavigation().stop();
|
||||||
|
mob.setTarget(null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -24,8 +24,6 @@ public interface Disguise extends FlightType.Provider, PlayerDimensions.Provider
|
||||||
|
|
||||||
EntityAppearance getDisguise();
|
EntityAppearance getDisguise();
|
||||||
|
|
||||||
void setDirty();
|
|
||||||
|
|
||||||
boolean isDead();
|
boolean isDead();
|
||||||
|
|
||||||
default Optional<EntityAppearance> getAppearance() {
|
default Optional<EntityAppearance> getAppearance() {
|
||||||
|
@ -57,7 +55,6 @@ public interface Disguise extends FlightType.Provider, PlayerDimensions.Provider
|
||||||
}
|
}
|
||||||
|
|
||||||
getDisguise().setAppearance(entity);
|
getDisguise().setAppearance(entity);
|
||||||
setDirty();
|
|
||||||
return this;
|
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.mob.UEntityAttributes;
|
||||||
import com.minelittlepony.unicopia.entity.player.PlayerDimensions;
|
import com.minelittlepony.unicopia.entity.player.PlayerDimensions;
|
||||||
import com.minelittlepony.unicopia.entity.player.Pony;
|
import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
import com.minelittlepony.unicopia.network.track.TrackableObject;
|
||||||
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
|
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
|
||||||
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
import com.minelittlepony.unicopia.util.NbtSerialisable;
|
||||||
import com.mojang.authlib.GameProfile;
|
import com.mojang.authlib.GameProfile;
|
||||||
|
@ -51,7 +52,7 @@ import net.minecraft.nbt.NbtElement;
|
||||||
import net.minecraft.util.math.Vec3d;
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.util.shape.VoxelShape;
|
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);
|
private static final Optional<Float> BLOCK_HEIGHT = Optional.of(0.5F);
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
@ -77,6 +78,8 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi
|
||||||
@Nullable
|
@Nullable
|
||||||
private NbtCompound entityNbt;
|
private NbtCompound entityNbt;
|
||||||
|
|
||||||
|
private boolean dirty;
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
public Entity getAppearance() {
|
public Entity getAppearance() {
|
||||||
return entity;
|
return entity;
|
||||||
|
@ -109,6 +112,7 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi
|
||||||
|
|
||||||
entityNbt = entity == null ? null : encodeEntityToNBT(entity);
|
entityNbt = entity == null ? null : encodeEntityToNBT(entity);
|
||||||
entityId = entityNbt == null ? "" : entityNbt.getString("id");
|
entityId = entityNbt == null ? "" : entityNbt.getString("id");
|
||||||
|
markDirty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isPresent() {
|
public boolean isPresent() {
|
||||||
|
@ -392,4 +396,44 @@ public class EntityAppearance implements NbtSerialisable, PlayerDimensions.Provi
|
||||||
getAttachments().forEach(e -> EntityCollisions.getCollissionShapes(e.entity(), context, output));
|
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);
|
} 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);
|
mob.getWorld().spawnEntity(clone);
|
||||||
|
|
||||||
if (!mob.isSilent()) {
|
if (!mob.isSilent()) {
|
||||||
|
|
|
@ -20,11 +20,11 @@ import net.minecraft.util.Identifier;
|
||||||
import net.minecraft.registry.Registries;
|
import net.minecraft.registry.Registries;
|
||||||
|
|
||||||
public interface UPotions {
|
public interface UPotions {
|
||||||
MorphingPotion MORPH_EARTH_PONY = new MorphingPotion(Race.EARTH).registerBaseRecipes(Potions.STRENGTH, UItems.CURING_JOKE);
|
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);
|
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.HIPPOGRIFF_BADGE, Items.FEATHER);
|
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_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_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);
|
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.PlacementControlSpell;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
|
import com.minelittlepony.unicopia.ability.magic.spell.Situation;
|
||||||
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
|
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.ability.magic.spell.effect.SpellType;
|
||||||
import com.minelittlepony.unicopia.entity.EntityPhysics;
|
import com.minelittlepony.unicopia.entity.EntityPhysics;
|
||||||
import com.minelittlepony.unicopia.entity.EntityReference;
|
import com.minelittlepony.unicopia.entity.EntityReference;
|
||||||
|
@ -70,8 +71,12 @@ public class CastSpellEntity extends LightEmittingEntity implements Caster<CastS
|
||||||
this.controllingEntityUuid = caster.asEntity().getUuid();
|
this.controllingEntityUuid = caster.asEntity().getUuid();
|
||||||
this.controllingSpellUuid = control.getUuid();
|
this.controllingSpellUuid = control.getUuid();
|
||||||
setCaster(caster);
|
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) {
|
public CastSpellEntity(EntityType<?> type, World world) {
|
||||||
|
|
|
@ -58,6 +58,8 @@ public class Acrobatics implements Tickable, NbtSerialisable {
|
||||||
public void tick() {
|
public void tick() {
|
||||||
BlockPos climbingPos = entity.getClimbingPos().orElse(null);
|
BlockPos climbingPos = entity.getClimbingPos().orElse(null);
|
||||||
|
|
||||||
|
BlockPos hangingPos = pony.getPhysics().getHeadPosition();
|
||||||
|
|
||||||
if (!pony.getPhysics().isFlying() && !entity.getAbilities().flying
|
if (!pony.getPhysics().isFlying() && !entity.getAbilities().flying
|
||||||
&& climbingPos != null
|
&& climbingPos != null
|
||||||
&& pony.getObservedSpecies() == Race.CHANGELING
|
&& pony.getObservedSpecies() == Race.CHANGELING
|
||||||
|
@ -68,7 +70,8 @@ public class Acrobatics implements Tickable, NbtSerialisable {
|
||||||
}
|
}
|
||||||
|
|
||||||
distanceClimbed += Math.abs(pony.getMotion().getClientVelocity().y);
|
distanceClimbed += Math.abs(pony.getMotion().getClientVelocity().y);
|
||||||
BlockPos hangingPos = entity.getBlockPos().up();
|
|
||||||
|
|
||||||
boolean canhangHere = canHangAt(hangingPos);
|
boolean canhangHere = canHangAt(hangingPos);
|
||||||
|
|
||||||
if (distanceClimbed > 1.5) {
|
if (distanceClimbed > 1.5) {
|
||||||
|
@ -156,8 +159,9 @@ public class Acrobatics implements Tickable, NbtSerialisable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void startHanging(BlockPos pos) {
|
public void startHanging(BlockPos pos) {
|
||||||
|
boolean inverted = pony.getPhysics().isGravityNegative();
|
||||||
hangingPos.set(Optional.of(pos));
|
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.setVelocity(Vec3d.ZERO);
|
||||||
entity.setSneaking(false);
|
entity.setSneaking(false);
|
||||||
entity.stopFallFlying();
|
entity.stopFallFlying();
|
||||||
|
@ -165,14 +169,17 @@ public class Acrobatics implements Tickable, NbtSerialisable {
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean canHangAt(BlockPos pos) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pos = pos.up();
|
pos = pos.up(gravity);
|
||||||
BlockState state = pony.asWorld().getBlockState(pos);
|
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() {
|
private boolean canKeepHanging() {
|
||||||
|
@ -184,7 +191,7 @@ public class Acrobatics implements Tickable, NbtSerialisable {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return getHangingPosition().filter(hangingPos -> {
|
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();
|
}).isPresent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -242,7 +242,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
|
||||||
public void tick() {
|
public void tick() {
|
||||||
super.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));
|
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);
|
pony.getMagicalReserves().getCharge().set(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!creative) {
|
if (!creative && !pony.isClient()) {
|
||||||
checkAvianTakeoffConditions(velocity);
|
checkAvianTakeoffConditions(velocity);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -377,16 +377,17 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
|
||||||
tickGrounded();
|
tickGrounded();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!entity.isOnGround()) {
|
|
||||||
float heavyness = 1 - EnchantmentHelper.getEquipmentLevel(UEnchantments.HEAVY, entity) * 0.015F;
|
|
||||||
velocity.x /= heavyness;
|
|
||||||
velocity.z /= heavyness;
|
|
||||||
}
|
|
||||||
|
|
||||||
float maximum = 1.5F;
|
float maximum = 1.5F;
|
||||||
velocity.x = MathHelper.clamp(velocity.x, -maximum, maximum);
|
velocity.x = MathHelper.clamp(velocity.x, -maximum, maximum);
|
||||||
velocity.y = MathHelper.clamp(velocity.y, -maximum, maximum);
|
velocity.y = MathHelper.clamp(velocity.y, -maximum, maximum);
|
||||||
velocity.z = MathHelper.clamp(velocity.z, -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());
|
entity.setVelocity(velocity.toImmutable());
|
||||||
|
|
||||||
if (isFlying() && !entity.isFallFlying() && !pony.getAcrobatics().isHanging() && pony.isClient()) {
|
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);
|
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) {
|
if (pony.getObservedSpecies() != Race.BAT && entity.getWorld().random.nextInt(9000) == 0) {
|
||||||
entity.dropItem(pony.getObservedSpecies() == Race.HIPPOGRIFF ? UItems.GRYPHON_FEATHER : UItems.PEGASUS_FEATHER);
|
entity.dropItem(pony.getObservedSpecies() == Race.HIPPOGRIFF ? UItems.GRYPHON_FEATHER : UItems.PEGASUS_FEATHER);
|
||||||
playSound(USounds.ENTITY_PLAYER_PEGASUS_MOLT, 0.3F, 1);
|
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) {
|
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) {
|
private void tickNaturalFlight(MutableVector velocity) {
|
||||||
|
@ -689,7 +690,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
|
||||||
if (entity.getWorld().hasRain(entity.getBlockPos())) {
|
if (entity.getWorld().hasRain(entity.getBlockPos())) {
|
||||||
applyTurbulance(velocity);
|
applyTurbulance(velocity);
|
||||||
} else {
|
} 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;
|
targetUpdraft *= 1 + motion;
|
||||||
if (isGravityNegative()) {
|
if (isGravityNegative()) {
|
||||||
targetUpdraft *= -1;
|
targetUpdraft *= -1;
|
||||||
|
@ -829,8 +830,8 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
|
||||||
.reduce(0, (u, pos) -> {
|
.reduce(0, (u, pos) -> {
|
||||||
if (pony.canModifyAt(pos, ModificationType.PHYSICAL)) {
|
if (pony.canModifyAt(pos, ModificationType.PHYSICAL)) {
|
||||||
if (isEarthPonySmash) {
|
if (isEarthPonySmash) {
|
||||||
BlockDestructionManager.of(entity.getWorld()).damageBlock(pos, (int)entity.getWorld().getRandom().nextTriangular(5, 3));
|
float destruction = BlockDestructionManager.of(entity.getWorld()).damageBlock(pos, (int)entity.getWorld().getRandom().nextTriangular(5, 3));
|
||||||
if (BlockDestructionManager.of(entity.getWorld()).getBlockDestruction(pos) >= 9) {
|
if (destruction >= BlockDestructionManager.MAX_DAMAGE - 1 && pony.canModifyAt(pos, ModificationType.PHYSICAL)) {
|
||||||
entity.getWorld().breakBlock(pos, true);
|
entity.getWorld().breakBlock(pos, true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -862,7 +863,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
|
||||||
if (isFlying()) {
|
if (isFlying()) {
|
||||||
playSound(USounds.ENTITY_PLAYER_PEGASUS_DASH, 1, 1);
|
playSound(USounds.ENTITY_PLAYER_PEGASUS_DASH, 1, 1);
|
||||||
} else {
|
} 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;
|
return compositeRace;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean collidesWithClouds() {
|
||||||
|
return getCompositeRace().canInteractWithClouds() || entity.isCreative();
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setSpecies(Race race) {
|
public void setSpecies(Race race) {
|
||||||
race = race.validate(entity);
|
race = race.validate(entity);
|
||||||
|
@ -597,7 +602,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
float lightScale = light / 15F;
|
float lightScale = light / 15F;
|
||||||
float approachFactor = ((velocityScale + lightScale) / 2F);
|
float approachFactor = ((velocityScale + lightScale) / 2F);
|
||||||
|
|
||||||
if (approachFactor < (entity.isSneaking() ? 0.8F : 0.6F)) {
|
if (approachFactor < (entity.isSneaking() ? 0.8F : 0.3F)) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -703,7 +708,7 @@ public class Pony extends Living<PlayerEntity> implements Copyable<Pony>, Update
|
||||||
if (EffectUtils.hasExtraDefenses(entity)) {
|
if (EffectUtils.hasExtraDefenses(entity)) {
|
||||||
double radius = distance / 10;
|
double radius = distance / 10;
|
||||||
if (radius > 0) {
|
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() {
|
public ActionResult canSleepNow() {
|
||||||
if (asWorld().getGameRules().getBoolean(UGameRules.DO_NOCTURNAL_BAT_PONIES) && getSpecies().isNocturnal()) {
|
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;
|
return ActionResult.PASS;
|
||||||
|
|
|
@ -101,7 +101,7 @@ public class AmuletItem extends WearableItem implements ChargeableItem {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static TrinketsDelegate.EquippedStack get(LivingEntity entity) {
|
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()
|
.findFirst()
|
||||||
.orElse(TrinketsDelegate.EquippedStack.EMPTY);
|
.orElse(TrinketsDelegate.EquippedStack.EMPTY);
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,12 +18,13 @@ public class HeavyProjectileItem extends ProjectileItem {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public PhysicsBodyProjectileEntity createProjectile(ItemStack stack, World world, @Nullable PlayerEntity player) {
|
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) {
|
if (player != null) {
|
||||||
projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1);
|
projectile.setVelocity(player, player.getPitch(), player.getYaw(), 0, 1.5F, 1);
|
||||||
}
|
}
|
||||||
projectile.pickupType = PersistentProjectileEntity.PickupPermission.ALLOWED;
|
projectile.pickupType = PersistentProjectileEntity.PickupPermission.ALLOWED;
|
||||||
projectile.setStack(stack.copy().split(1));
|
|
||||||
return projectile;
|
return projectile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -7,14 +7,17 @@ import com.google.common.collect.Multimap;
|
||||||
import com.minelittlepony.unicopia.UTags;
|
import com.minelittlepony.unicopia.UTags;
|
||||||
import com.minelittlepony.unicopia.entity.Living;
|
import com.minelittlepony.unicopia.entity.Living;
|
||||||
import com.minelittlepony.unicopia.entity.mob.UEntityAttributes;
|
import com.minelittlepony.unicopia.entity.mob.UEntityAttributes;
|
||||||
|
import com.minelittlepony.unicopia.item.enchantment.CustomEnchantableItem;
|
||||||
|
|
||||||
import net.minecraft.block.*;
|
import net.minecraft.block.*;
|
||||||
|
import net.minecraft.enchantment.Enchantment;
|
||||||
|
import net.minecraft.enchantment.Enchantments;
|
||||||
import net.minecraft.entity.EquipmentSlot;
|
import net.minecraft.entity.EquipmentSlot;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.attribute.*;
|
import net.minecraft.entity.attribute.*;
|
||||||
import net.minecraft.item.*;
|
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");
|
static final UUID ATTACK_RANGE_MODIFIER_ID = UUID.fromString("A7B3659C-AA74-469C-963A-09A391DCAA0F");
|
||||||
|
|
||||||
private final Multimap<EntityAttribute, EntityAttributeModifier> attributeModifiers;
|
private final Multimap<EntityAttribute, EntityAttributeModifier> attributeModifiers;
|
||||||
|
@ -65,4 +68,9 @@ public class PolearmItem extends SwordItem {
|
||||||
|
|
||||||
return true;
|
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.BlockPointer;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.Direction;
|
import net.minecraft.util.math.Direction;
|
||||||
|
import net.minecraft.util.math.Position;
|
||||||
|
import net.minecraft.util.math.Vec3d;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
|
|
||||||
public class SpellbookItem extends BookItem implements Dispensable {
|
public class SpellbookItem extends BookItem implements Dispensable {
|
||||||
|
@ -29,17 +31,20 @@ public class SpellbookItem extends BookItem implements Dispensable {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public TypedActionResult<ItemStack> dispenseStack(BlockPointer source, ItemStack stack) {
|
public TypedActionResult<ItemStack> dispenseStack(BlockPointer pointer, ItemStack stack) {
|
||||||
Direction facing = source.state().get(DispenserBlock.FACING);
|
Direction facing = pointer.state().get(DispenserBlock.FACING);
|
||||||
BlockPos pos = source.pos().offset(facing);
|
Position pos = DispenserBlock.getOutputLocation(pointer);
|
||||||
|
|
||||||
float yaw = facing.getOpposite().asRotation();
|
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);
|
stack.decrement(1);
|
||||||
|
|
||||||
return new TypedActionResult<>(ActionResult.SUCCESS, stack);
|
return new TypedActionResult<>(ActionResult.SUCCESS, stack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return new TypedActionResult<>(ActionResult.FAIL, stack);
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ActionResult useOnBlock(ItemUsageContext context) {
|
public ActionResult useOnBlock(ItemUsageContext context) {
|
||||||
|
|
||||||
|
@ -49,24 +54,28 @@ public class SpellbookItem extends BookItem implements Dispensable {
|
||||||
if (!context.getWorld().isClient) {
|
if (!context.getWorld().isClient) {
|
||||||
BlockPos pos = context.getBlockPos().offset(context.getSide());
|
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) {
|
if (!player.getAbilities().creativeMode) {
|
||||||
player.getStackInHand(context.getHand()).decrement(1);
|
player.getStackInHand(context.getHand()).decrement(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ActionResult.SUCCESS;
|
return ActionResult.SUCCESS;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return ActionResult.PASS;
|
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);
|
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.setHeadYaw(yaw);
|
||||||
book.setYaw(yaw);
|
book.setYaw(yaw);
|
||||||
|
|
||||||
|
if (!book.canSpawn(world)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
@Nullable
|
@Nullable
|
||||||
NbtCompound tag = stack.getSubNbt("spellbookState");
|
NbtCompound tag = stack.getSubNbt("spellbookState");
|
||||||
if (tag != null) {
|
if (tag != null) {
|
||||||
|
@ -80,6 +89,8 @@ public class SpellbookItem extends BookItem implements Dispensable {
|
||||||
altar.generateDecorations(world);
|
altar.generateDecorations(world);
|
||||||
UCriteria.LIGHT_ALTAR.trigger(placer);
|
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 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 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 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.6F, 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.6F, 3, 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, 2, -3.6F, 4, 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, 2, -3.6F, 5, 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, 2, -3.6F, 5, new Item.Settings().fireproof()), 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 LOOT_BUG_SPAWN_EGG = register("loot_bug_spawn_egg", new SpawnEggItem(UEntities.LOOT_BUG, 0x3C9D14, 0xE66F16, new Item.Settings()), ItemGroups.SPAWN_EGGS);
|
||||||
Item BUTTERFLY_SPAWN_EGG = register("butterfly_spawn_egg", new SpawnEggItem(UEntities.BUTTERFLY, 0x222200, 0xAAEEFF, new Item.Settings()), ItemGroups.SPAWN_EGGS);
|
Item BUTTERFLY_SPAWN_EGG = register("butterfly_spawn_egg", new SpawnEggItem(UEntities.BUTTERFLY, 0x222200, 0xAAEEFF, new Item.Settings()), ItemGroups.SPAWN_EGGS);
|
||||||
|
|
|
@ -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;
|
package com.minelittlepony.unicopia.mixin;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
|
@ -9,7 +11,9 @@ import com.minelittlepony.unicopia.entity.player.Pony;
|
||||||
|
|
||||||
import net.minecraft.enchantment.Enchantment;
|
import net.minecraft.enchantment.Enchantment;
|
||||||
import net.minecraft.enchantment.EnchantmentHelper;
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
|
import net.minecraft.enchantment.EnchantmentLevelEntry;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
|
import net.minecraft.item.ItemStack;
|
||||||
|
|
||||||
@Mixin(EnchantmentHelper.class)
|
@Mixin(EnchantmentHelper.class)
|
||||||
abstract class MixinEnchantmentHelper {
|
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;
|
package com.minelittlepony.unicopia.mixin;
|
||||||
|
|
||||||
import java.util.function.Supplier;
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
import org.spongepowered.asm.mixin.Mixin;
|
import org.spongepowered.asm.mixin.Mixin;
|
||||||
import org.spongepowered.asm.mixin.injection.At;
|
import org.spongepowered.asm.mixin.injection.At;
|
||||||
import org.spongepowered.asm.mixin.injection.Inject;
|
import org.spongepowered.asm.mixin.injection.Inject;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||||
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.entity.duck.RotatedView;
|
import com.minelittlepony.unicopia.entity.duck.RotatedView;
|
||||||
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
import com.minelittlepony.unicopia.server.world.BlockDestructionManager;
|
||||||
|
import com.minelittlepony.unicopia.server.world.WeatherAccess;
|
||||||
|
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.World;
|
import net.minecraft.world.World;
|
||||||
import net.minecraft.world.WorldAccess;
|
import net.minecraft.world.WorldAccess;
|
||||||
|
|
||||||
@Mixin(World.class)
|
@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);
|
private final Supplier<BlockDestructionManager> destructions = BlockDestructionManager.create((World)(Object)this);
|
||||||
|
|
||||||
|
@Nullable
|
||||||
|
private Float rainGradientOverride;
|
||||||
|
@Nullable
|
||||||
|
private Float thunderGradientOverride;
|
||||||
|
|
||||||
private boolean mirrorEntityStatuses;
|
private boolean mirrorEntityStatuses;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -28,11 +39,36 @@ abstract class MixinWorld implements WorldAccess, BlockDestructionManager.Source
|
||||||
return destructions.get();
|
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"))
|
@Inject(method = "sendEntityStatus(Lnet/minecraft/entity/Entity;B)V", at = @At("HEAD"))
|
||||||
private void onSendEntityStatus(Entity entity, byte status, CallbackInfo info) {
|
private void onSendEntityStatus(Entity entity, byte status, CallbackInfo info) {
|
||||||
if (mirrorEntityStatuses) {
|
if (mirrorEntityStatuses) {
|
||||||
entity.handleStatus(status);
|
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.CallbackInfo;
|
||||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||||
|
|
||||||
import com.minelittlepony.unicopia.EquinePredicates;
|
|
||||||
import com.minelittlepony.unicopia.client.BatEyesApplicator;
|
import com.minelittlepony.unicopia.client.BatEyesApplicator;
|
||||||
import com.minelittlepony.unicopia.client.UnicopiaClient;
|
import com.minelittlepony.unicopia.client.UnicopiaClient;
|
||||||
import com.minelittlepony.unicopia.client.render.shader.ViewportShader;
|
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.client.util.math.MatrixStack;
|
||||||
import net.minecraft.util.math.RotationAxis;
|
import net.minecraft.util.math.RotationAxis;
|
||||||
import net.minecraft.entity.LivingEntity;
|
import net.minecraft.entity.LivingEntity;
|
||||||
import net.minecraft.entity.effect.StatusEffects;
|
|
||||||
import net.minecraft.resource.SynchronousResourceReloader;
|
import net.minecraft.resource.SynchronousResourceReloader;
|
||||||
|
|
||||||
@Mixin(value = GameRenderer.class, priority = Integer.MAX_VALUE)
|
@Mixin(value = GameRenderer.class, priority = Integer.MAX_VALUE)
|
||||||
|
@ -46,21 +44,11 @@ abstract class MixinGameRenderer implements AutoCloseable, SynchronousResourceRe
|
||||||
BatEyesApplicator.INSTANCE.disable();
|
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",
|
@Inject(method = "getNightVisionStrength(Lnet/minecraft/entity/LivingEntity;F)F",
|
||||||
at = @At("RETURN"),
|
at = @At("RETURN"),
|
||||||
cancellable = true)
|
cancellable = true)
|
||||||
private static void onGetNightVisionStrengthReturn(LivingEntity entity, float tickDelta, CallbackInfoReturnable<Float> info) {
|
private static void onGetNightVisionStrengthReturn(LivingEntity entity, float tickDelta, CallbackInfoReturnable<Float> info) {
|
||||||
if (entity.hasStatusEffect(StatusEffects.NIGHT_VISION) && EquinePredicates.PLAYER_BAT.test(entity)) {
|
info.setReturnValue(BatEyesApplicator.INSTANCE.getWorldBrightness(info.getReturnValueF(), entity, tickDelta));
|
||||||
info.setReturnValue(UnicopiaClient.getWorldBrightness(info.getReturnValueF()));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Inject(method = "render",
|
@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.ClientBlockDestructionManager;
|
||||||
import com.minelittlepony.unicopia.client.UnicopiaClient;
|
import com.minelittlepony.unicopia.client.UnicopiaClient;
|
||||||
|
import com.minelittlepony.unicopia.server.world.WeatherAccess;
|
||||||
|
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||||
import net.minecraft.client.render.BlockBreakingInfo;
|
import net.minecraft.client.render.BlockBreakingInfo;
|
||||||
import net.minecraft.client.render.Camera;
|
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.util.math.MatrixStack;
|
||||||
import net.minecraft.client.world.ClientWorld;
|
import net.minecraft.client.world.ClientWorld;
|
||||||
import net.minecraft.resource.SynchronousResourceReloader;
|
import net.minecraft.resource.SynchronousResourceReloader;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.util.math.RotationAxis;
|
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)
|
@Mixin(value = WorldRenderer.class, priority = 1001)
|
||||||
abstract class MixinWorldRenderer implements SynchronousResourceReloader, AutoCloseable, ClientBlockDestructionManager.Source {
|
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_X.rotationDegrees(UnicopiaClient.getInstance().getSkyAngleDelta(tickDelta)));
|
||||||
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(UnicopiaClient.getInstance().tangentalSkyAngle.getValue()));
|
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