Implemented the bounce and poisoned joked enchants

This commit is contained in:
Sollace 2021-02-16 23:12:09 +02:00
parent ea07545d34
commit be59ed0553
20 changed files with 241 additions and 48 deletions

View file

@ -25,8 +25,7 @@ import net.minecraft.util.registry.Registry;
public class TreeTypeLoader extends JsonDataLoader implements IdentifiableResourceReloadListener {
private static final Identifier ID = new Identifier("unicopia", "data/tree_type");
private static final Gson GSON = new GsonBuilder()
public static final Gson GSON = new GsonBuilder()
.registerTypeAdapter(Identifier.class, new ToStringAdapter<>(Identifier::new))
.create();

View file

@ -5,14 +5,14 @@ import net.minecraft.util.Identifier;
import net.minecraft.util.registry.Registry;
public interface USounds {
SoundEvent AMBIENT_WIND_GUST = register("ambient.wind.gust");
SoundEvent WING_FLAP = register("wing_flap");
SoundEvent WIND_RUSH = register("wind_rush");
SoundEvent ENTITY_PLAYER_BATPONY_SCREECH = register("entity.player.batpony.screech");
SoundEvent ENTITY_PLAYER_REBOUND = register("entity.player.rebound");
SoundEvent ENTITY_PLAYER_PEGASUS_WINGSFLAP = register("entity.player.pegasus.wingsflap");
SoundEvent ENTITY_PLAYER_CHANGELING_BUZZ = register("entity.player.changeling.buzz");
SoundEvent BATPONY_EEEE = register("batpony_eeee");
SoundEvent CHANGELING_BUZZ = register("changeling_buzz");
SoundEvent AURA = register("aura");
SoundEvent ITEM_MAGIC_AURA = register("item.magic.aura");
SoundEvent RECORD_CRUSADE = register("record.crusade");
SoundEvent RECORD_PET = register("record.pet");

View file

@ -11,6 +11,7 @@ import org.apache.logging.log4j.Logger;
import com.minelittlepony.unicopia.command.Commands;
import com.minelittlepony.unicopia.entity.effect.UPotions;
import com.minelittlepony.unicopia.item.UItems;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.network.Channel;
public class Unicopia implements ModInitializer {
@ -41,6 +42,7 @@ public class Unicopia implements ModInitializer {
((BlockDestructionManager.Source)w).getDestructionManager().tick();
});
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(TreeTypeLoader.INSTANCE);
ResourceManagerHelper.get(ResourceType.SERVER_DATA).registerReloadListener(UEnchantments.POISON_JOKE);
UItems.bootstrap();
UPotions.bootstrap();

View file

@ -61,14 +61,14 @@ public class BatEeeeAbility implements Ability<Hit> {
int count = 1 + rng.nextInt(10);
for (int i = 0; i < count; i++) {
player.getWorld().playSound(null, player.getOrigin(), USounds.BATPONY_EEEE, SoundCategory.PLAYERS,
player.getWorld().playSound(null, player.getOrigin(), USounds.ENTITY_PLAYER_BATPONY_SCREECH, SoundCategory.PLAYERS,
0.9F + (rng.nextFloat() - 0.5F) / 2F,
1.6F + (rng.nextFloat() - 0.5F)
);
}
AwaitTickQueue.scheduleTask(player.getWorld(), w -> {
for (int i = 0; i < count; i++) {
player.getWorld().playSound(null, player.getOrigin(), USounds.BATPONY_EEEE, SoundCategory.PLAYERS,
player.getWorld().playSound(null, player.getOrigin(), USounds.ENTITY_PLAYER_BATPONY_SCREECH, SoundCategory.PLAYERS,
0.9F + (rng.nextFloat() - 0.5F) / 2F,
1.6F + (rng.nextFloat() - 0.5F)
);

View file

@ -116,6 +116,10 @@ public class EarthPonyStompAbility implements Ability<Hit> {
}
}
if (i instanceof LivingEntity) {
amount /= 1 + (EnchantmentHelper.getEquipmentLevel(UEnchantments.PADDED, (LivingEntity)i) / 6F);
}
i.damage(damage, (float)amount);
}
});

View file

@ -162,7 +162,7 @@ public class ShieldSpell extends AbstractRangedAreaSpell implements Attached {
target.playSound(SoundEvents.ENTITY_ZOMBIE_VILLAGER_CURE, 0.1F, 1);
target.remove();
} else {
ricochet(target, pos);
ProjectileUtil.ricochet(target, pos, 0.9F);
}
}
} else if (target instanceof LivingEntity) {
@ -214,21 +214,6 @@ public class ShieldSpell extends AbstractRangedAreaSpell implements Attached {
return force;
}
/**
* Reverses a projectiles direction to deflect it off the shield's surface.
*/
protected void ricochet(Entity projectile, Vec3d pos) {
Vec3d position = projectile.getPos();
Vec3d motion = projectile.getVelocity();
Vec3d normal = position.subtract(pos).normalize();
Vec3d approach = motion.subtract(normal);
if (approach.length() >= motion.length()) {
ProjectileUtil.setThrowableHeading(projectile, normal, (float)motion.length(), 0);
}
}
class Target {
int cooldown = 20;

View file

@ -23,7 +23,7 @@ public class MagicAuraSoundInstance extends MovingSoundInstance {
private boolean fadingOut;
public MagicAuraSoundInstance(SoundCategory category, Living<?> living) {
super(USounds.AURA, category);
super(USounds.ITEM_MAGIC_AURA, category);
this.looping = true;
this.repeat = true;
this.living = living;

View file

@ -7,6 +7,7 @@ import com.minelittlepony.unicopia.ability.magic.Spell;
import com.minelittlepony.unicopia.entity.EntityPhysics;
import com.minelittlepony.unicopia.entity.player.MagicReserves.Bar;
import com.minelittlepony.unicopia.item.enchantment.UEnchantments;
import com.minelittlepony.unicopia.projectile.ProjectileUtil;
import com.minelittlepony.unicopia.util.NbtSerialisable;
import com.minelittlepony.unicopia.util.MutableVector;
@ -38,6 +39,8 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
public boolean isFlyingEither = false;
public boolean isFlyingSurvival = false;
private int wallHitCooldown;
private Vec3d lastPos = Vec3d.ZERO;
private final PlayerDimensions dimensions;
@ -69,6 +72,9 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
@Override
public void tick() {
if (wallHitCooldown > 0) {
wallHitCooldown--;
}
PlayerEntity entity = pony.getMaster();
if (isGravityNegative() && !entity.isSneaking() && entity.isInSneakingPose()) {
@ -97,9 +103,15 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
if (entity.abilities.flying && entity.horizontalCollision) {
handleWallCollission(entity, velocity);
entity.setVelocity(velocity.toImmutable());
entity.abilities.flying = false;
return;
}
entity.abilities.flying = false;
isFlyingSurvival = entity.abilities.flying && !creative;
isFlyingEither = isFlyingSurvival || (creative && entity.abilities.flying);
}
}
@ -210,26 +222,41 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
}
private SoundEvent getWingSound() {
return pony.getSpecies() == Race.CHANGELING ? USounds.CHANGELING_BUZZ : USounds.WING_FLAP;
return pony.getSpecies() == Race.CHANGELING ? USounds.ENTITY_PLAYER_CHANGELING_BUZZ : USounds.ENTITY_PLAYER_PEGASUS_WINGSFLAP;
}
protected void handleWallCollission(PlayerEntity player, MutableVector velocity) {
if (!player.world.isClient) {
BlockPos pos = new BlockPos(player.getCameraPosVec(1).add(player.getRotationVec(1).normalize().multiply(2)));
if (wallHitCooldown > 0) {
return;
}
BlockState state = player.world.getBlockState(pos);
BlockPos pos = new BlockPos(player.getCameraPosVec(1).add(player.getRotationVec(1).normalize().multiply(2)));
if (!player.world.isAir(pos) && Block.isFaceFullSquare(state.getCollisionShape(player.world, pos), player.getHorizontalFacing().getOpposite())) {
double motion = Math.sqrt(getHorizontalMotion(player));
BlockState state = player.world.getBlockState(pos);
float distance = (float)(motion * 20 - 3);
if (!player.world.isAir(pos) && Block.isFaceFullSquare(state.getCollisionShape(player.world, pos), player.getHorizontalFacing().getOpposite())) {
double motion = Math.sqrt(getHorizontalMotion(player));
if (distance > 0) {
player.playSound(distance > 4 ? SoundEvents.ENTITY_PLAYER_BIG_FALL : SoundEvents.ENTITY_PLAYER_SMALL_FALL, 1, 1);
float distance = (float)(motion * 20 - 3);
player.damage(DamageSource.FLY_INTO_WALL, distance);
float bouncyness = EnchantmentHelper.getEquipmentLevel(UEnchantments.PADDED, player) * 6;
System.out.println(bouncyness);
if (distance > 0) {
wallHitCooldown = 30;
if (bouncyness > 0) {
player.world.playSoundFromEntity(null, player, USounds.ENTITY_PLAYER_REBOUND, SoundCategory.PLAYERS, 1, 1);
ProjectileUtil.ricochet(player, Vec3d.of(pos), 0.4F + Math.min(2, bouncyness / 18F));
velocity.fromImmutable(player.getVelocity());
distance /= bouncyness;
} else {
player.world.playSoundFromEntity(null, player, distance > 4 ? SoundEvents.ENTITY_PLAYER_BIG_FALL : SoundEvents.ENTITY_PLAYER_SMALL_FALL, SoundCategory.PLAYERS, 1, 1);
//player.playSound(distance > 4 ? SoundEvents.ENTITY_PLAYER_BIG_FALL : SoundEvents.ENTITY_PLAYER_SMALL_FALL, 1, 1);
}
player.damage(DamageSource.FLY_INTO_WALL, distance);
}
}
}
@ -298,7 +325,7 @@ public class PlayerPhysics extends EntityPhysics<Pony> implements Tickable, Moti
}
if (forward >= 1) {
player.world.playSound(null, player.getBlockPos(), USounds.WIND_RUSH, SoundCategory.AMBIENT, 3, 1);
player.world.playSound(null, player.getBlockPos(), USounds.AMBIENT_WIND_GUST, SoundCategory.AMBIENT, 3, 1);
}
forward = Math.min(forward, 7);

View file

@ -0,0 +1,117 @@
package com.minelittlepony.unicopia.item.enchantment;
import java.io.IOException;
import java.io.InputStreamReader;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.apache.commons.lang3.reflect.TypeUtils;
import com.google.gson.JsonParseException;
import com.minelittlepony.unicopia.TreeTypeLoader;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.entity.Living;
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
import net.minecraft.entity.EquipmentSlot;
import net.minecraft.resource.Resource;
import net.minecraft.resource.ResourceManager;
import net.minecraft.sound.SoundCategory;
import net.minecraft.sound.SoundEvent;
import net.minecraft.util.Identifier;
import net.minecraft.util.profiler.Profiler;
import net.minecraft.util.registry.Registry;
public class PoisonedJokeEnchantment extends SimpleEnchantment implements IdentifiableResourceReloadListener {
private static final Identifier ID = new Identifier("unicopia", "data/poisoned_joke_sounds");
private static final Type TYPE = TypeUtils.parameterize(List.class, Identifier.class);
private List<SoundEvent> sounds = new ArrayList<>();
protected PoisonedJokeEnchantment() {
super(Rarity.COMMON, true, 1, EquipmentSlot.values());
}
@Override
public void onUserTick(Living<?> user, int level) {
if (sounds.isEmpty() || user.getWorld().isClient) {
return;
}
int light = user.getWorld().getLightLevel(user.getEntity().getRootVehicle().getBlockPos());
Random rng = user.getWorld().random;
Data data = user.getEnchants().computeIfAbsent(this, Data::new);
data.level -= rng.nextFloat() * 0.8F;
if (rng.nextInt(Math.max(1, (light * 9) + (int)data.level)) == 0) {
data.level = rng.nextInt(5000);
Unicopia.LOGGER.info("Boo!");
user.getWorld().playSoundFromEntity(
null,
user.getEntity(),
sounds.get(rng.nextInt(sounds.size())), SoundCategory.HOSTILE,
0.5F + rng.nextFloat() * 0.5F,
0.5F + rng.nextFloat() * 0.5F
);
}
}
@Override
public Identifier getFabricId() {
return ID;
}
@Override
public CompletableFuture<Void> reload(Synchronizer sync, ResourceManager manager,
Profiler serverProfiler, Profiler clientProfiler,
Executor serverExecutor, Executor clientExecutor) {
return sync.whenPrepared(null).thenRunAsync(() -> {
clientProfiler.startTick();
clientProfiler.push("Loading poisoned joke sound options");
sounds = manager.getAllNamespaces().stream()
.map(domain -> new Identifier(domain, "poisoned_joke_sounds.json"))
.flatMap(id -> getResources(manager, id))
.flatMap(this::loadFile)
.distinct()
.flatMap(this::findSound)
.collect(Collectors.toList());
clientProfiler.pop();
clientProfiler.endTick();
}, clientExecutor);
}
private Stream<Resource> getResources(ResourceManager manager, Identifier id) {
try {
return manager.getAllResources(id).stream();
} catch (IOException ignored) { }
return Stream.empty();
}
private Stream<Identifier> loadFile(Resource res) throws JsonParseException {
try (Resource resource = res) {
return (TreeTypeLoader.GSON.<List<Identifier>>fromJson(new InputStreamReader(resource.getInputStream()), TYPE)).stream();
} catch (JsonParseException e) {
Unicopia.LOGGER.warn("Failed to load sounds file at " + res.getResourcePackName(), e);
} catch (IOException ignored) {}
return Stream.empty();
}
private Stream<SoundEvent> findSound(Identifier id) {
SoundEvent value = Registry.SOUND_EVENT.getOrEmpty(id).orElse(null);
if (value == null) {
Unicopia.LOGGER.warn("Could not find sound with id {}", id);
return Stream.empty();
}
return Stream.of(value);
}
}

View file

@ -25,8 +25,6 @@ public interface UEnchantments {
/**
* Protects against wall collisions and earth pony attacks!
*
* TODO:
*/
Enchantment PADDED = register("padded", new SimpleEnchantment(Rarity.COMMON, EnchantmentTarget.ARMOR, false, 3, EquipmentSlot.HEAD, EquipmentSlot.CHEST, EquipmentSlot.LEGS, EquipmentSlot.FEET));
@ -56,10 +54,8 @@ public interface UEnchantments {
* Hahaha geddit?
*
* Random things happen.
*
* TODO:
*/
Enchantment POISON_JOKE = register("poison_joke", new SimpleEnchantment(Rarity.COMMON, true, 3, EquipmentSlot.values()));
PoisonedJokeEnchantment POISON_JOKE = register("poison_joke", new PoisonedJokeEnchantment());
/**
* Who doesn't like a good freakout?

View file

@ -52,4 +52,21 @@ public interface ProjectileUtil {
throwable.addVelocity(heading.x - vel.x, heading.y - vel.y, heading.z - vel.z);
}
}
/**
* Reverses a projectile's direction to deflect it off a surface.
*/
static void ricochet(Entity projectile, Vec3d pos, float absorbtionRate) {
Vec3d position = projectile.getPos();
Vec3d motion = projectile.getVelocity();
Vec3d normal = position.subtract(pos).normalize();
Vec3d approach = motion.subtract(normal);
if (approach.length() < motion.length()) {
normal = normal.multiply(-1);
}
setThrowableHeading(projectile, normal, (float)motion.length() * absorbtionRate, 0);
}
}

View file

@ -14,6 +14,12 @@ public class MutableVector {
z = vec.z;
}
public void fromImmutable(Vec3d vec) {
x = vec.x;
y = vec.y;
z = vec.z;
}
public Vec3d toImmutable() {
return new Vec3d(x, y, z);
}

View file

@ -1,5 +1,5 @@
{
"wing_flap": {
"entity.player.pegasus.wingsflap": {
"category": "player",
"subtitle": "unicopia.subtitle.flap_wings",
"sounds": [
@ -9,13 +9,24 @@
"unicopia:wing/wing3"
]
},
"aura": {
"item.magic.aura": {
"category": "player",
"sounds": [
"unicopia:aura/aura0"
]
},
"batpony_eeee": {
"entity.player.rebound": {
"category": "player",
"sounds": [
"unicopia:boing/boing0",
"unicopia:boing/boing1",
"unicopia:boing/boing2",
"unicopia:boing/boing3",
"unicopia:boing/boing4",
"unicopia:boing/boing5"
]
},
"entity.player.batpony.screech": {
"category": "player",
"subtitle": "unicopia.subtitle.batpony_eeee",
"sounds": [
@ -25,7 +36,7 @@
"unicopia:batpony/screep1"
]
},
"changeling_buzz": {
"entity.player.changeling.buzz": {
"category": "player",
"subtitle": "unicopia.subtitle.changeling_buzz",
"sounds": [
@ -34,7 +45,7 @@
"unicopia:cicada/cicada_6"
]
},
"wind_rush": {
"ambient.wind.gust": {
"category": "ambient",
"subtitle": "unicopia.subtitle.wind_rush",
"sounds": [

View file

@ -0,0 +1,29 @@
[
"minecraft:ambient.cave",
"minecraft:entity.creeper.primed",
"minecraft:block.stone_button.click_on",
"minecraft:block.stone_button.click_off",
"minecraft:block.wooden_pressure_plate.click_on",
"minecraft:block.wooden_door.close",
"minecraft:block.stone.break",
"minecraft:item.shield.break",
"minecraft:entity.blaze.ambient",
"minecraft:entity.zombie.ambient",
"minecraft:entity.drowned.ambient",
"minecraft:entity.endermite.ambient",
"minecraft:entity.skeleton.ambient",
"minecraft:entity.skeleton_horse.ambient",
"minecraft:entity.zoglin.ambient",
"minecraft:entity.zombified_piglin.ambient",
"minecraft:entity.zombie.break_wooden_door",
"minecraft:music.menu",
"minecraft:entity.tnt.primed",
"minecraft:entity.generic.explode",
"minecraft:ambient.nether_wastes.loop",
"minecraft:ambient.nether_wastes.mood",
"minecraft:ambient.crimson_forest.mood",
"minecraft:ambient.basalt_deltas.mood",
"minecraft:ambient.basalt_deltas.loop",
"minecraft:ambient.underwater.loop.additions.ultra_rare",
"minecraft:ambient.underwater.loop.additions.rare"
]