Rewrite the dark vortex to cause less lag and adjust/apply a cap to its maximum size

This commit is contained in:
Sollace 2024-04-07 20:27:15 +01:00
parent 835834a468
commit 12bc0b6973
No known key found for this signature in database
GPG key ID: E52FACE7B5C773DB
8 changed files with 205 additions and 134 deletions

View file

@ -1,8 +1,12 @@
package com.minelittlepony.unicopia.ability.magic.spell.effect;
import java.util.Optional;
import org.jetbrains.annotations.Nullable;
import com.minelittlepony.unicopia.USounds;
import com.minelittlepony.unicopia.UTags;
import com.minelittlepony.unicopia.Unicopia;
import com.minelittlepony.unicopia.ability.magic.Affine;
import com.minelittlepony.unicopia.ability.magic.Caster;
import com.minelittlepony.unicopia.ability.magic.spell.CastingMethod;
@ -12,6 +16,7 @@ import com.minelittlepony.unicopia.ability.magic.spell.trait.SpellTraits;
import com.minelittlepony.unicopia.ability.magic.spell.trait.Trait;
import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.entity.damage.UDamageTypes;
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
import com.minelittlepony.unicopia.particle.FollowingParticleEffect;
import com.minelittlepony.unicopia.particle.LightningBoltParticleEffect;
import com.minelittlepony.unicopia.particle.ParticleUtils;
@ -19,10 +24,12 @@ import com.minelittlepony.unicopia.particle.UParticles;
import com.minelittlepony.unicopia.projectile.MagicBeamEntity;
import com.minelittlepony.unicopia.projectile.MagicProjectileEntity;
import com.minelittlepony.unicopia.projectile.ProjectileDelegate;
import com.minelittlepony.unicopia.server.world.UGameRules;
import com.minelittlepony.unicopia.util.Lerp;
import com.minelittlepony.unicopia.util.shape.Sphere;
import net.minecraft.block.Blocks;
import net.minecraft.entity.Entity;
import net.minecraft.entity.FallingBlockEntity;
import net.minecraft.entity.player.PlayerEntity;
import net.minecraft.entity.projectile.PersistentProjectileEntity;
import net.minecraft.item.Item;
@ -39,7 +46,7 @@ import net.minecraft.world.World.ExplosionSourceType;
/**
* More powerful version of the vortex spell which creates a black hole.
*/
public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelegate.BlockHitListener {
public class DarkVortexSpell extends AbstractSpell implements ProjectileDelegate.BlockHitListener {
public static final SpellTraits DEFAULT_TRAITS = new SpellTraits.Builder()
.with(Trait.CHAOS, 5)
.with(Trait.KNOWLEDGE, 1)
@ -49,18 +56,34 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
private float accumulatedMass = 0;
private final TargetSelecter targetSelecter = new TargetSelecter(this).setFilter(this::isValidTarget).setTargetowner(true).setTargetAllies(true);
private final Lerp radius = new Lerp(0);
private int prevTicksDying;
private int ticksDying;
protected DarkVortexSpell(CustomisedSpellType<?> type) {
super(type);
targetSelecter.setTargetowner(true).setTargetAllies(true);
}
// 1. force decreases with distance: distance scale 1 -> 0
// 2. max force (at dist 0) is taken from accumulated mass
// 3. force reaches 0 at distance of drawDropOffRange
private double getMass() {
return 0.1F + accumulatedMass / 10F;
}
@Override
public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
if (!projectile.isClient() && projectile instanceof MagicBeamEntity source) {
BlockPos pos = hit.getBlockPos();
projectile.getWorld().createExplosion(projectile, pos.getX(), pos.getY(), pos.getZ(), 3, ExplosionSourceType.NONE);
toPlaceable().tick(source, Situation.BODY);
public double getEventHorizonRadius() {
return radius.getValue();
}
public double getDrawDropOffRange() {
return getEventHorizonRadius() * 20;
}
private double getAttractiveForce(Caster<?> source, Entity target) {
return AttractionUtils.getAttractiveForce(getMass(), getOrigin(source), target);
}
@Override
@ -78,23 +101,96 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
if (situation == Situation.BODY) {
return true;
}
double mass = getMass() * 0.1;
double logarithm = 1 - (1D / (1 + (mass * mass)));
radius.update((float)Math.max(0.1, logarithm * source.asWorld().getGameRules().getInt(UGameRules.MAX_DARK_VORTEX_SIZE)), 200L);
if (source.asEntity().age % 20 == 0) {
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_ADDITIONS, SoundCategory.AMBIENT, 1, 1);
}
if (!source.isClient() && source.asWorld().random.nextInt(300) == 0) {
double eventHorizon = getEventHorizonRadius();
if (source.isClient()) {
if (eventHorizon > 0.3) {
double range = eventHorizon * 2;
Vec3d origin = getOrigin(source);
source.spawnParticles(origin, new Sphere(false, range), 50, p -> {
source.addParticle(
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, origin, 0.4F)
.withChild(source.asWorld().isAir(BlockPos.ofFloored(p)) ? ParticleTypes.SMOKE : ParticleTypes.CAMPFIRE_SIGNAL_SMOKE),
p,
Vec3d.ZERO
);
});
}
} else if (source.asWorld().random.nextInt(300) == 0) {
ParticleUtils.spawnParticle(source.asWorld(), LightningBoltParticleEffect.DEFAULT, getOrigin(source), Vec3d.ZERO);
}
super.tick(source, situation);
if (!source.isClient()) {
if (eventHorizon > 2) {
Vec3d origin = getOrigin(source);
new Sphere(false, eventHorizon + 3).translate(origin).randomPoints(10, source.asWorld().random).forEach(i -> {
BlockPos pos = BlockPos.ofFloored(i);
if (!source.asWorld().isAir(pos)) {
new Sphere(false, 3).translate(i).getBlockPositions().forEach(p -> {
affectBlock(source, p, origin);
});
ParticleUtils.spawnParticle(source.asWorld(), new LightningBoltParticleEffect(true, 10, 6, 3, Optional.of(i)), getOrigin(source), Vec3d.ZERO);
}
});
}
}
Vec3d origin = getOrigin(source);
for (Entity insideEntity : source.findAllEntitiesInRange(eventHorizon * 0.5F).toList()) {
insideEntity.setVelocity(Vec3d.ZERO);
Living.updateVelocity(insideEntity);
if (insideEntity instanceof CastSpellEntity s && getType().isOn(insideEntity)) {
setDead();
s.getSpellSlot().clear();
source.asWorld().createExplosion(source.asEntity(), source.getOrigin().getX(), source.getOrigin().getY(), source.getOrigin().getZ(), 12, ExplosionSourceType.NONE);
source.asWorld().createExplosion(source.asEntity(), insideEntity.getX(), insideEntity.getY(), insideEntity.getZ(), 12, ExplosionSourceType.NONE);
return false;
}
}
targetSelecter.getEntities(source, getDrawDropOffRange()).forEach(i -> {
try {
affectEntity(source, i, i.getPos().distanceTo(origin));
} catch (Throwable e) {
Unicopia.LOGGER.error("Error updating radial effect", e);
}
});
if (!source.subtractEnergyCost(-accumulatedMass)) {
setDead();
source.asWorld().createExplosion(source.asEntity(), source.getOrigin().getX(), source.getOrigin().getY(), source.getOrigin().getZ(), 3, ExplosionSourceType.NONE);
}
return true;
}
@Override
protected void consumeManage(Caster<?> source, long costMultiplier, float knowledge) {
if (!source.subtractEnergyCost(-accumulatedMass)) {
setDead();
public void tickDying(Caster<?> source) {
accumulatedMass /= 2D;
double mass = getMass() * 0.1;
double logarithm = 1 - (1D / (1 + (mass * mass)));
radius.update((float)Math.max(0.1, logarithm * source.asWorld().getGameRules().getInt(UGameRules.MAX_DARK_VORTEX_SIZE)), 200L);
prevTicksDying = ticksDying;
if (ticksDying++ > 25) {
super.tickDying(source);
}
}
@Override
public void onImpact(MagicProjectileEntity projectile, BlockHitResult hit) {
if (!projectile.isClient() && projectile instanceof MagicBeamEntity source) {
BlockPos pos = hit.getBlockPos();
projectile.getWorld().createExplosion(projectile, pos.getX(), pos.getY(), pos.getZ(), 12, ExplosionSourceType.NONE);
toPlaceable().tick(source, Situation.BODY);
}
}
@ -103,102 +199,49 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
return accumulatedMass < 4;
}
@Override
protected boolean isValidTarget(Caster<?> source, Entity entity) {
private boolean isValidTarget(Caster<?> source, Entity entity) {
return EntityPredicates.EXCEPT_CREATIVE_OR_SPECTATOR.test(entity) && getAttractiveForce(source, entity) > 0;
}
@Override
public void generateParticles(Caster<?> source) {
super.generateParticles(source);
if (getEventHorizonRadius() > 0.3) {
double range = getDrawDropOffRange(source);
Vec3d origin = getOrigin(source);
source.spawnParticles(origin, new Sphere(false, range), 1, p -> {
if (!source.asWorld().isAir(BlockPos.ofFloored(p))) {
source.addParticle(
new FollowingParticleEffect(UParticles.HEALTH_DRAIN, origin, 0.4F)
.withChild(ParticleTypes.CAMPFIRE_SIGNAL_SMOKE),
p,
Vec3d.ZERO
);
}
});
}
public Vec3d getOrigin(Caster<?> source) {
return source.asEntity().getPos().add(0, getYOffset(), 0);
}
@Override
public double getDrawDropOffRange(Caster<?> source) {
return getEventHorizonRadius() * 20;
public double getYOffset() {
return 3 - radius.getValue() * 0.5;
}
@Override
protected Vec3d getOrigin(Caster<?> source) {
return source.getOriginVector().add(0, getEventHorizonRadius() / 2D, 0);
}
@Override
protected long applyEntities(Caster<?> source) {
if (!source.isClient()) {
double radius = getEventHorizonRadius();
if (radius > 2) {
Vec3d origin = getOrigin(source);
new Sphere(false, radius).translate(origin).getBlockPositions().forEach(i -> {
if (!canAffect(source, i)) {
return;
}
if (source.getOrigin().isWithinDistance(i, getEventHorizonRadius() / 2)) {
source.asWorld().breakBlock(i, false);
} else {
CatapultSpell.createBlockEntity(source.asWorld(), i, e -> {
applyRadialEffect(source, e, e.getPos().distanceTo(origin), radius);
});
}
});
}
}
return super.applyEntities(source);
}
protected boolean canAffect(Caster<?> source, BlockPos pos) {
private boolean canAffect(Caster<?> source, BlockPos pos) {
return source.canModifyAt(pos)
&& source.asWorld().getFluidState(pos).isEmpty()
&& source.asWorld().getBlockState(pos).getHardness(source.asWorld(), pos) >= 0;
&& source.asWorld().getBlockState(pos).getHardness(source.asWorld(), pos) >= 0
&& !source.asWorld().getBlockState(pos).isIn(UTags.Blocks.CATAPULT_IMMUNE);
}
// 1. force decreases with distance: distance scale 1 -> 0
// 2. max force (at dist 0) is taken from accumulated mass
// 3. force reaches 0 at distance of drawDropOffRange
public double getEventHorizonRadius() {
return Math.sqrt(Math.max(0.001, getMass() / 3F));
private void affectBlock(Caster<?> source, BlockPos pos, Vec3d origin) {
if (!canAffect(source, pos)) {
if (source.asWorld().getBlockState(pos).isOf(Blocks.BEDROCK)) {
source.asWorld().setBlockState(pos, Blocks.BARRIER.getDefaultState());
}
private double getAttractiveForce(Caster<?> source, Entity target) {
return AttractionUtils.getAttractiveForce(getMass(), getOrigin(source), target);
}
private double getMass() {
return 0.1F + accumulatedMass / 10F;
}
@Override
protected void applyRadialEffect(Caster<?> source, Entity target, double distance, double radius) {
if (target instanceof FallingBlockEntity && source.isClient()) {
return;
}
if (distance <= getEventHorizonRadius() + 0.5) {
target.setVelocity(target.getVelocity().multiply(distance / (2 * radius)));
if (distance < 1) {
target.setVelocity(target.getVelocity().multiply(distance));
if (source.getOrigin().isWithinDistance(pos, getEventHorizonRadius())) {
source.asWorld().breakBlock(pos, false);
if (!source.asWorld().getFluidState(pos).isEmpty()) {
source.asWorld().setBlockState(pos, Blocks.AIR.getDefaultState());
}
} else {
CatapultSpell.createBlockEntity(source.asWorld(), pos, e -> {
e.addVelocity(0, 0.1, 0);
if (e instanceof PlayerEntity) {
affectEntity(source, e, e.getPos().distanceTo(getOrigin(source)));
}
});
}
}
private void affectEntity(Caster<?> source, Entity target, double distance) {
if (distance <= getEventHorizonRadius() + 0.5) {
target.setVelocity(target.getVelocity().multiply(distance < 1 ? distance : distance / (2 * getEventHorizonRadius())));
Living.updateVelocity(target);
@Nullable
@ -227,14 +270,18 @@ public class DarkVortexSpell extends AttractiveSpell implements ProjectileDelega
target.damage(source.damageOf(UDamageTypes.GAVITY_WELL_RECOIL, source), Integer.MAX_VALUE);
if (!(target instanceof PlayerEntity)) {
target.discard();
source.asWorld().playSound(null, source.getOrigin(), USounds.ENCHANTMENT_CONSUMPTION_CONSUME, SoundCategory.AMBIENT, 2, 0.02F);
source.asWorld().playSound(null, target.getBlockPos(), USounds.AMBIENT_DARK_VORTEX_MOOD, SoundCategory.AMBIENT, 2, 0.002F);
}
if (target.isAlive()) {
target.damage(source.asEntity().getDamageSources().outOfWorld(), Integer.MAX_VALUE);
}
source.subtractEnergyCost(-massOfTarget * 10);
source.asWorld().playSound(null, source.getOrigin(), USounds.AMBIENT_DARK_VORTEX_MOOD, SoundCategory.AMBIENT, 2, 0.02F);
if (target instanceof PlayerEntity && distance < getEventHorizonRadius() + 5) {
source.asWorld().playSound(null, target.getBlockPos(), USounds.AMBIENT_DARK_VORTEX_MOOD, SoundCategory.AMBIENT, 2, 0.02F);
}
} else {
double force = getAttractiveForce(source, target);

View file

@ -198,7 +198,7 @@ public class UHud {
float vortexDistortion = DarkVortexSpellRenderer.getCameraDistortion();
if (vortexDistortion > 20) {
if (vortexDistortion > 25) {
context.fill(RenderLayers.getEndPortal(), 0, 0, scaledWidth, scaledHeight, 0);
context.getMatrices().push();
context.getMatrices().translate(scaledWidth / 2, scaledHeight / 2, 0);
@ -206,7 +206,7 @@ public class UHud {
context.getMatrices().pop();
return;
} else if (vortexDistortion > 0) {
context.fill(0, 0, scaledWidth, scaledHeight, (int)((vortexDistortion / 20F) * 255) << 24);
context.fill(0, 0, scaledWidth, scaledHeight, (int)((Math.min(20, vortexDistortion) / 20F) * 255) << 24);
}
boolean hasEffect = client.player.hasStatusEffect(UEffects.SUN_BLINDNESS);

View file

@ -8,11 +8,11 @@ import com.minelittlepony.unicopia.client.render.RenderLayers;
import com.minelittlepony.unicopia.client.render.model.PlaneModel;
import com.minelittlepony.unicopia.client.render.model.SphereModel;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.render.Camera;
import net.minecraft.client.render.RenderLayer;
import net.minecraft.client.render.VertexConsumer;
import net.minecraft.client.render.VertexConsumerProvider;
import net.minecraft.client.util.math.MatrixStack;
import net.minecraft.entity.Entity;
import net.minecraft.util.Identifier;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RotationAxis;
@ -36,65 +36,79 @@ public class DarkVortexSpellRenderer extends SpellRenderer<DarkVortexSpell> {
@Override
public void render(MatrixStack matrices, VertexConsumerProvider vertices, DarkVortexSpell spell, Caster<?> caster, int light, float limbAngle, float limbDistance, float tickDelta, float animationProgress, float headYaw, float headPitch) {
super.render(matrices, vertices, spell, caster, light, limbAngle, limbDistance, tickDelta, animationProgress, headYaw, headPitch);
Entity cameraEntity = MinecraftClient.getInstance().getCameraEntity();
Camera camera = MinecraftClient.getInstance().gameRenderer.getCamera();
float radius = (float)spell.getEventHorizonRadius();
float absDistance = (float)cameraEntity.getEyePos().distanceTo(caster.getOriginVector().add(0, 2, 0));
float absDistance = (float)camera.getPos().distanceTo(spell.getOrigin(caster));
matrices.push();
matrices.translate(0, 2 + radius, 0);
matrices.translate(0, spell.getYOffset(), 0);
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getSolid()), light, 1, Math.min(radius * 0.6F, absDistance * 0.1F), 0, 0, 0, 1);
float visualRadius = Math.min(radius * 0.8F, absDistance - 1F);
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getSolid()), light, 1, visualRadius, 0, 0, 0, 1);
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getMagicColored()), light, 1, visualRadius + 0.05F, 0, 0, 0, 0.9F);
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getMagicColored()), light, 1, visualRadius + 0.1F, 0, 0, 0, 0.9F);
SphereModel.SPHERE.render(matrices, vertices.getBuffer(RenderLayers.getMagicColored()), light, 1, visualRadius + 0.15F, 0, 0, 0, 0.9F);
matrices.push();
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(90));
matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90 + cameraEntity.getYaw(tickDelta)));
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-cameraEntity.getPitch(tickDelta)));
matrices.multiply(RotationAxis.NEGATIVE_X.rotationDegrees(90 + camera.getYaw()));
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(-camera.getPitch()));
matrices.scale(0.7F, 1, 1);
float distance = 1F / MathHelper.clamp((absDistance / (radius * 4)), 0.0000001F, 1);
float distance = 1F / MathHelper.clamp(absDistance / (radius + 7), 0.0000001F, 1);
distance *= distance;
if (absDistance < radius * 4) {
cameraDistortion += distance;
}
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getEndPortal()), light, 1, radius * 0.5F, 0, 0, 0, 0);
matrices.push();
matrices.scale(distance, distance, distance);
if (absDistance > radius) {
matrices.push();
matrices.translate(0, -0.1F, 0);
for (int i = 0; i < 10; i++) {
matrices.scale(1, 1, 0.796F);
float brightness = i / 10F;
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getMagicNoColor()), light, 1, radius * (1 + (0.25F * i)) * 0.7F, brightness, brightness, brightness, 0.2F);
}
matrices.pop();
}
matrices.pop();
SphereModel.DISK.render(matrices, vertices.getBuffer(RenderLayers.getEndPortal()), light, 1, radius * 0.5F, 1, 0.5F, 0, 1);
if (radius > 0.3F && absDistance > radius) {
radius *= Math.min(2, 3 + radius);
matrices.scale(radius, radius, radius);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90));
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(animationProgress * 168));
float processionSpeed = animationProgress * 0.02F;
float maxProcessionAngle = 15;
float range = (float)spell.getDrawDropOffRange() / 8F;
matrices.scale(range, range, range);
matrices.multiply(RotationAxis.POSITIVE_X.rotationDegrees(90 + MathHelper.cos(processionSpeed) * maxProcessionAngle));
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(MathHelper.sin(processionSpeed) * maxProcessionAngle));
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(animationProgress * 18));
VertexConsumer buffer = vertices.getBuffer(RenderLayer.getEntityTranslucent(ACCRETION_DISK_TEXTURE));
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
matrices.push();
matrices.scale(0.5F, 0.5F, 0.5F);
matrices.scale(0.9F, 0.9F, 0.9F);
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(33));
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
matrices.pop();
matrices.multiply(RotationAxis.POSITIVE_Y.rotationDegrees(45));
matrices.scale(0.9F, 0.9F, 0.9F);
matrices.multiply(RotationAxis.POSITIVE_Z.rotationDegrees(33));
PlaneModel.INSTANCE.render(matrices, buffer, light, 0, 1, 1, 1, 1, 1);
}
matrices.pop();

View file

@ -14,6 +14,9 @@ import com.minelittlepony.unicopia.ability.magic.SpellContainer.Operation;
import com.minelittlepony.unicopia.ability.magic.spell.Spell;
import com.minelittlepony.unicopia.ability.magic.spell.effect.SpellType;
import com.minelittlepony.unicopia.entity.Living;
import com.minelittlepony.unicopia.entity.mob.CastSpellEntity;
import com.minelittlepony.unicopia.entity.player.Pony;
import net.fabricmc.fabric.api.resource.IdentifiableResourceReloadListener;
import net.minecraft.client.MinecraftClient;
import net.minecraft.client.font.TextRenderer.TextLayerType;
@ -91,6 +94,9 @@ public class SpellEffectsRenderDispatcher implements SynchronousResourceReloader
if (client.getEntityRenderDispatcher().shouldRenderHitboxes()
&& !client.hasReducedDebugInfo()
&& !(caster.asEntity() == client.cameraEntity && client.options.getPerspective() == Perspective.FIRST_PERSON)) {
if (!(caster instanceof Pony || caster instanceof CastSpellEntity)) {
return;
}
renderHotspot(matrices, vertices, caster, animationProgress);
renderSpellDebugInfo(matrices, vertices, caster, light);
}

View file

@ -44,7 +44,11 @@ public class UBlockTagProvider extends FabricTagProvider.BlockTagProvider {
UBlocks.GOLDEN_OAK_SPROUT
};
getOrCreateTagBuilder(UTags.Blocks.CATAPULT_IMMUNE).add(Blocks.BEDROCK).forceAddTag(BlockTags.DOORS).forceAddTag(BlockTags.TRAPDOORS);
getOrCreateTagBuilder(UTags.Blocks.CATAPULT_IMMUNE).add(
Blocks.STRUCTURE_VOID, Blocks.STRUCTURE_BLOCK,
Blocks.COMMAND_BLOCK, Blocks.CHAIN_COMMAND_BLOCK, Blocks.REPEATING_COMMAND_BLOCK,
Blocks.LIGHT, Blocks.JIGSAW, Blocks.BARRIER, Blocks.BEDROCK
).forceAddTag(BlockTags.DOORS).forceAddTag(BlockTags.TRAPDOORS);
getOrCreateTagBuilder(UTags.Blocks.BUTTERFLIES_SPAWNABLE_ON).forceAddTag(BlockTags.ANIMALS_SPAWNABLE_ON).forceAddTag(BlockTags.LEAVES).forceAddTag(BlockTags.FLOWERS).forceAddTag(BlockTags.FLOWER_POTS);
getOrCreateTagBuilder(UTags.Blocks.JARS).add(UBlocks.JAR, UBlocks.CLOUD_JAR, UBlocks.STORM_JAR, UBlocks.LIGHTNING_JAR, UBlocks.ZAP_JAR);
getOrCreateTagBuilder(BlockTags.CROPS).add(crops);

View file

@ -716,7 +716,7 @@ public class PlayerPhysics extends EntityPhysics<PlayerEntity> implements Tickab
}
private void applyTurbulance(MutableVector velocity) {
int globalEffectStrength = MathHelper.clamp(entity.getWorld().getGameRules().getInt(UGameRules.WEATHER_EFFECTS_STRENGTH), 0, 100);
int globalEffectStrength = entity.getWorld().getGameRules().getInt(UGameRules.WEATHER_EFFECTS_STRENGTH);
float effectStrength = Math.min(1, (float)ticksInAir / MAX_TICKS_TO_WEATHER_EFFECTS) * (globalEffectStrength / 100F);
Vec3d gust = WeatherConditions.getGustStrength(entity.getWorld(), entity.getBlockPos())
.multiply(globalEffectStrength / 100D)

View file

@ -1,15 +1,18 @@
package com.minelittlepony.unicopia.server.world;
import net.fabricmc.fabric.api.gamerule.v1.GameRuleFactory;
import net.fabricmc.fabric.api.gamerule.v1.GameRuleRegistry;
import net.minecraft.world.GameRules;
import net.minecraft.world.GameRules.BooleanRule;
import net.minecraft.world.GameRules.IntRule;
public interface UGameRules {
GameRules.Key<BooleanRule> SWAP_TRIBE_ON_DEATH = GameRules.register("swapTribeOnDeath", GameRules.Category.SPAWNING, BooleanRule.create(false));
GameRules.Key<BooleanRule> ANNOUNCE_TRIBE_JOINS = GameRules.register("announceTribeJoins", GameRules.Category.SPAWNING, BooleanRule.create(false));
GameRules.Key<BooleanRule> DO_NOCTURNAL_BAT_PONIES = GameRules.register("doNocturnalBatPonies", GameRules.Category.PLAYER, BooleanRule.create(true));
GameRules.Key<IntRule> WEATHER_EFFECTS_STRENGTH = GameRules.register("weatherEffectsStrength", GameRules.Category.MISC, IntRule.create(100));
GameRules.Key<BooleanRule> DO_TIME_MAGIC = GameRules.register("doTimeMagic", GameRules.Category.PLAYER, BooleanRule.create(true));
GameRules.Key<BooleanRule> SWAP_TRIBE_ON_DEATH = GameRuleRegistry.register("swapTribeOnDeath", GameRules.Category.SPAWNING, GameRuleFactory.createBooleanRule(false));
GameRules.Key<BooleanRule> ANNOUNCE_TRIBE_JOINS = GameRuleRegistry.register("announceTribeJoins", GameRules.Category.SPAWNING, GameRuleFactory.createBooleanRule(false));
GameRules.Key<BooleanRule> DO_NOCTURNAL_BAT_PONIES = GameRuleRegistry.register("doNocturnalBatPonies", GameRules.Category.PLAYER, GameRuleFactory.createBooleanRule(true));
GameRules.Key<IntRule> WEATHER_EFFECTS_STRENGTH = GameRuleRegistry.register("weatherEffectsStrength", GameRules.Category.MISC, GameRuleFactory.createIntRule(100, 0, 100));
GameRules.Key<BooleanRule> DO_TIME_MAGIC = GameRuleRegistry.register("doTimeMagic", GameRules.Category.PLAYER, GameRuleFactory.createBooleanRule(true));
GameRules.Key<IntRule> MAX_DARK_VORTEX_SIZE = GameRuleRegistry.register("maxDarkVortexSize", GameRules.Category.PLAYER, GameRuleFactory.createIntRule(20, 1, 25));
static void bootstrap() { }
}

View file

@ -6,9 +6,6 @@ accessible class net/minecraft/client/render/item/HeldItemRenderer$H
accessible class net/minecraft/client/render/VertexConsumers$Union
accessible class net/minecraft/client/gui/hud/InGameHud$HeartType
accessible method net/minecraft/world/GameRules register (Ljava/lang/String;Lnet/minecraft/world/GameRules$Category;Lnet/minecraft/world/GameRules$Type;)Lnet/minecraft/world/GameRules$Key;
accessible method net/minecraft/world/GameRules$BooleanRule create (Z)Lnet/minecraft/world/GameRules$Type;
accessible method net/minecraft/world/GameRules$IntRule create (I)Lnet/minecraft/world/GameRules$Type;
accessible method net/minecraft/world/gen/foliage/FoliagePlacerType <init> (Lcom/mojang/serialization/Codec;)V
accessible field net/minecraft/entity/mob/CreeperEntity CHARGED Lnet/minecraft/entity/data/TrackedData;