Compare commits

...

4 commits

Author SHA1 Message Date
Ell
4af1787320 fixed some issues with the ward effect 2023-02-16 20:01:21 +01:00
Ell
d73751b536 finished the aura imbalance ward 2023-02-16 19:45:20 +01:00
Ell
b3f2a61e5d lower limiter, part 1 2023-02-16 19:03:26 +01:00
Ell
7d23cafc77 added bottled vacuum 2023-02-16 16:24:47 +01:00
55 changed files with 513 additions and 160 deletions

View file

@ -0,0 +1,7 @@
{
"variants": {
"": {
"model": "naturesaura:block/lower_limiter"
}
}
}

View file

@ -0,0 +1,8 @@
{
"parent": "minecraft:block/cube_bottom_top",
"textures": {
"bottom": "naturesaura:block/lower_limiter_top",
"side": "naturesaura:block/lower_limiter",
"top": "naturesaura:block/lower_limiter_top"
}
}

View file

@ -0,0 +1,3 @@
{
"parent": "naturesaura:block/lower_limiter"
}

View file

@ -0,0 +1,6 @@
{
"parent": "minecraft:item/generated",
"textures": {
"layer0": "naturesaura:item/vacuum_bottle"
}
}

View file

@ -1,15 +1,15 @@
{
"values": [
"naturesaura:flower_generator",
"naturesaura:ancient_log",
"naturesaura:offering_table",
"naturesaura:ancient_planks",
"naturesaura:ancient_stairs",
"naturesaura:oak_generator",
"naturesaura:wood_stand",
"naturesaura:ancient_bark",
"naturesaura:ancient_slab",
"naturesaura:nether_wart_mushroom",
"naturesaura:auto_crafter"
"naturesaura:oak_generator",
"naturesaura:auto_crafter",
"naturesaura:ancient_bark",
"naturesaura:ancient_planks",
"naturesaura:ancient_stairs",
"naturesaura:flower_generator",
"naturesaura:wood_stand",
"naturesaura:offering_table"
]
}

View file

@ -1,46 +1,47 @@
{
"values": [
"naturesaura:gold_brick",
"naturesaura:spring",
"naturesaura:aura_detector",
"naturesaura:infused_slab",
"naturesaura:tainted_gold_block",
"naturesaura:grated_chute",
"naturesaura:snow_creator",
"naturesaura:infused_brick",
"naturesaura:weather_changer",
"naturesaura:infused_brick_slab",
"naturesaura:field_creator",
"naturesaura:infused_stone",
"naturesaura:time_changer",
"naturesaura:nature_altar",
"naturesaura:placer",
"naturesaura:firework_generator",
"naturesaura:infused_stairs",
"naturesaura:projectile_generator",
"naturesaura:item_distributor",
"naturesaura:chunk_loader",
"naturesaura:rf_converter",
"naturesaura:spawn_lamp",
"naturesaura:blast_furnace_booster",
"naturesaura:nether_grass",
"naturesaura:animal_container",
"naturesaura:moss_generator",
"naturesaura:generator_limit_remover",
"naturesaura:pickup_stopper",
"naturesaura:aura_timer",
"naturesaura:animal_spawner",
"naturesaura:ender_crate",
"naturesaura:animal_generator",
"naturesaura:chorus_generator",
"naturesaura:hopper_upgrade",
"naturesaura:furnace_heater",
"naturesaura:potion_generator",
"naturesaura:infused_brick_stairs",
"naturesaura:infused_iron_block",
"naturesaura:aura_detector",
"naturesaura:spawn_lamp",
"naturesaura:animal_container",
"naturesaura:powder_placer",
"naturesaura:weather_changer",
"naturesaura:grated_chute",
"naturesaura:crushing_catalyst",
"naturesaura:conversion_catalyst",
"naturesaura:ender_crate",
"naturesaura:firework_generator",
"naturesaura:tainted_gold_block",
"naturesaura:placer",
"naturesaura:blast_furnace_booster",
"naturesaura:lower_limiter",
"naturesaura:animal_generator",
"naturesaura:nether_grass",
"naturesaura:infused_iron_block",
"naturesaura:snow_creator",
"naturesaura:infused_stone",
"naturesaura:field_creator",
"naturesaura:nature_altar",
"naturesaura:gold_nether_brick",
"naturesaura:gold_brick"
"naturesaura:aura_timer",
"naturesaura:chunk_loader",
"naturesaura:animal_spawner",
"naturesaura:chorus_generator",
"naturesaura:infused_brick_slab",
"naturesaura:projectile_generator",
"naturesaura:furnace_heater",
"naturesaura:moss_generator",
"naturesaura:rf_converter",
"naturesaura:item_distributor",
"naturesaura:time_changer",
"naturesaura:conversion_catalyst",
"naturesaura:hopper_upgrade",
"naturesaura:pickup_stopper",
"naturesaura:infused_brick",
"naturesaura:generator_limit_remover",
"naturesaura:infused_slab"
]
}

View file

@ -0,0 +1,20 @@
{
"type": "minecraft:block",
"pools": [
{
"bonus_rolls": 0.0,
"conditions": [
{
"condition": "minecraft:survives_explosion"
}
],
"entries": [
{
"type": "minecraft:item",
"name": "naturesaura:lower_limiter"
}
],
"rolls": 1.0
}
]
}

View file

@ -60,9 +60,8 @@ public class BlockChunkLoader extends BlockContainerImpl implements IVisualizabl
if (!ModConfig.instance.chunkLoader.get())
return;
var tile = levelIn.getBlockEntity(pos);
if (tile instanceof BlockEntityChunkLoader) {
var range = ((BlockEntityChunkLoader) tile).range();
for (var i = Mth.ceil(range / 8F); i > 0; i--) {
if (tile instanceof BlockEntityChunkLoader loader && loader.canUseRightNow(loader.getAuraUsed())) {
for (var i = Mth.ceil(loader.range() / 8F); i > 0; i--) {
NaturesAuraAPI.instance().spawnMagicParticle(
pos.getX() + levelIn.random.nextFloat(), pos.getY() + levelIn.random.nextFloat(), pos.getZ() + levelIn.random.nextFloat(),
0, 0, 0, 0xa12dff, 1F + levelIn.random.nextFloat(), 100, 0, false, true);

View file

@ -91,7 +91,7 @@ public class BlockEnderCrate extends BlockContainerImpl implements ITESRProvider
public InteractionResult use(BlockState state, Level levelIn, BlockPos pos, Player player, InteractionHand handIn, BlockHitResult hit) {
if (!levelIn.isClientSide) {
var tile = levelIn.getBlockEntity(pos);
if (tile instanceof BlockEntityEnderCrate crate && crate.canOpen()) {
if (tile instanceof BlockEntityEnderCrate crate && crate.canOpen() && crate.canUseRightNow(2500)) {
crate.drainAura(2500);
NetworkHooks.openScreen((ServerPlayer) player, crate, pos);
}

View file

@ -0,0 +1,31 @@
package de.ellpeck.naturesaura.blocks;
import de.ellpeck.naturesaura.blocks.tiles.BlockEntityLowerLimiter;
import de.ellpeck.naturesaura.blocks.tiles.ModBlockEntities;
import de.ellpeck.naturesaura.blocks.tiles.render.RenderLowerLimiter;
import de.ellpeck.naturesaura.data.BlockStateGenerator;
import de.ellpeck.naturesaura.reg.ICustomBlockState;
import de.ellpeck.naturesaura.reg.ITESRProvider;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderers;
import net.minecraft.world.level.block.SoundType;
import net.minecraft.world.level.material.Material;
public class BlockLowerLimiter extends BlockContainerImpl implements ICustomBlockState, ITESRProvider<BlockEntityLowerLimiter> {
public BlockLowerLimiter() {
super("lower_limiter", BlockEntityLowerLimiter.class, Properties.of(Material.STONE).strength(2F).sound(SoundType.STONE));
}
@Override
public void generateCustomBlockState(BlockStateGenerator generator) {
generator.simpleBlock(this, generator.models().cubeBottomTop(this.getBaseName(),
generator.modLoc("block/" + this.getBaseName()),
generator.modLoc("block/" + this.getBaseName() + "_top"),
generator.modLoc("block/" + this.getBaseName() + "_top")));
}
@Override
public void registerTESR() {
BlockEntityRenderers.register(ModBlockEntities.LOWER_LIMITER, RenderLowerLimiter::new);
}
}

View file

@ -10,7 +10,6 @@ import de.ellpeck.naturesaura.packet.PacketHandler;
import de.ellpeck.naturesaura.packet.PacketParticles;
import de.ellpeck.naturesaura.reg.ICustomBlockState;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.entity.Mob;
import net.minecraft.world.level.BlockGetter;
import net.minecraft.world.level.Level;
@ -45,15 +44,16 @@ public class BlockSpawnLamp extends BlockContainerImpl implements IVisualizable,
@SubscribeEvent
public void onSpawn(LivingSpawnEvent.CheckSpawn event) {
var amountToUse = 200;
if (event.getSpawner() != null)
return;
var level = event.getLevel();
var accessor = event.getLevel();
var pos = new BlockPos(event.getX(), event.getY(), event.getZ());
if (!(level instanceof Level))
if (!(accessor instanceof Level level))
return;
var data = (LevelData) ILevelData.getLevelData((Level) level);
var data = (LevelData) ILevelData.getLevelData(level);
for (var lamp : data.spawnLamps) {
if (lamp.isRemoved())
if (lamp.isRemoved() || !lamp.canUseRightNow(amountToUse))
continue;
var range = lamp.getRadius();
@ -66,10 +66,10 @@ public class BlockSpawnLamp extends BlockContainerImpl implements IVisualizable,
var entity = (Mob) event.getEntity();
if (entity.checkSpawnRules(level, event.getSpawnReason()) && entity.checkSpawnObstruction(level)) {
var spot = IAuraChunk.getHighestSpot((Level) level, lampPos, 32, lampPos);
IAuraChunk.getAuraChunk((Level) level, spot).drainAura(spot, 200);
var spot = IAuraChunk.getHighestSpot(level, lampPos, 32, lampPos);
IAuraChunk.getAuraChunk(level, spot).drainAura(spot, amountToUse);
PacketHandler.sendToAllAround((ServerLevel) level, lampPos, 32,
PacketHandler.sendToAllAround(level, lampPos, 32,
new PacketParticles(lampPos.getX(), lampPos.getY(), lampPos.getZ(), PacketParticles.Type.SPAWN_LAMP));
}

View file

@ -58,10 +58,9 @@ public class BlockSpring extends BlockContainerImpl implements ICustomBlockState
@Override
public ItemStack pickupBlock(LevelAccessor levelIn, BlockPos pos, BlockState state) {
var tile = levelIn.getBlockEntity(pos);
if (tile instanceof BlockEntitySpring)
((BlockEntitySpring) tile).consumeAura(2500);
return new ItemStack(Items.WATER_BUCKET);
if (levelIn.getBlockEntity(pos) instanceof BlockEntitySpring spring && spring.tryConsumeAura(2500))
return new ItemStack(Items.WATER_BUCKET);
return ItemStack.EMPTY;
}
@Override

View file

@ -2,7 +2,7 @@ package de.ellpeck.naturesaura.blocks;
import net.minecraft.world.level.block.Block;
@SuppressWarnings("NonConstantFieldWithUpperCaseName")
@SuppressWarnings("FieldNamingConvention")
public final class ModBlocks {
public static Block ANCIENT_LOG;
@ -74,4 +74,5 @@ public final class ModBlocks {
public static Block CRIMSON_AURA_MUSHROOM;
public static Block AURA_MUSHROOM;
public static Block WEATHER_CHANGER;
public static Block LOWER_LIMITER;
}

View file

@ -51,6 +51,9 @@ public class BlockEntityAnimalSpawner extends BlockEntityImpl implements ITickab
if (this.currentRecipe != null) {
var drain = Mth.ceil(this.currentRecipe.aura / (float) this.currentRecipe.time * 10F);
if (!this.canUseRightNow(drain))
return;
var spot = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 35, this.worldPosition);
IAuraChunk.getAuraChunk(this.level, spot).drainAura(spot, drain);
@ -164,4 +167,9 @@ public class BlockEntityAnimalSpawner extends BlockEntityImpl implements ITickab
}
}
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}

View file

@ -28,6 +28,10 @@ public class BlockEntityBlastFurnaceBooster extends BlockEntityImpl implements I
if (this.level.isClientSide)
return;
var toUse = 6500;
if (!this.canUseRightNow(toUse))
return;
var below = this.level.getBlockEntity(this.worldPosition.below());
if (!(below instanceof BlastFurnaceBlockEntity tile))
return;
@ -60,7 +64,7 @@ public class BlockEntityBlastFurnaceBooster extends BlockEntityImpl implements I
}
var pos = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 30, this.worldPosition);
IAuraChunk.getAuraChunk(this.level, pos).drainAura(pos, 6500);
IAuraChunk.getAuraChunk(this.level, pos).drainAura(pos, toUse);
PacketHandler.sendToAllAround(this.level, this.worldPosition, 32,
new PacketParticles(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ(), PacketParticles.Type.BLAST_FURNACE_BOOSTER, 1));
@ -129,4 +133,9 @@ public class BlockEntityBlastFurnaceBooster extends BlockEntityImpl implements I
@Override
public void dropInventory() {
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}

View file

@ -18,6 +18,7 @@ public class BlockEntityChunkLoader extends BlockEntityImpl implements ITickable
private final List<ChunkPos> forcedChunks = new ArrayList<>();
private boolean firstTick = true;
private boolean canUseRightNow = true;
public BlockEntityChunkLoader(BlockPos pos, BlockState state) {
super(ModBlockEntities.CHUNK_LOADER, pos, state);
@ -42,6 +43,10 @@ public class BlockEntityChunkLoader extends BlockEntityImpl implements ITickable
return this.redstonePower * 2;
}
public int getAuraUsed() {
return Mth.ceil(this.range() / 2F);
}
private void loadChunks(boolean unload) {
if (this.level.isClientSide || !ModConfig.instance.chunkLoader.get())
return;
@ -50,7 +55,7 @@ public class BlockEntityChunkLoader extends BlockEntityImpl implements ITickable
List<ChunkPos> shouldBeForced = new ArrayList<>();
if (!unload) {
var range = this.range();
if (range > 0) {
if (range > 0 && this.canUseRightNow) {
for (var x = this.worldPosition.getX() - range >> 4; x <= this.worldPosition.getX() + range >> 4; x++) {
for (var z = this.worldPosition.getZ() - range >> 4; z <= this.worldPosition.getZ() + range >> 4; z++) {
var pos = new ChunkPos(x, z);
@ -86,10 +91,16 @@ public class BlockEntityChunkLoader extends BlockEntityImpl implements ITickable
this.firstTick = false;
}
var toUse = this.getAuraUsed();
var canUse = this.canUseRightNow(toUse);
if (this.canUseRightNow != canUse) {
this.canUseRightNow = canUse;
this.loadChunks(false);
}
if (this.level.getGameTime() % 20 != 0)
return;
var toUse = Mth.ceil(this.range() / 2F);
if (toUse > 0) {
if (toUse > 0 && this.canUseRightNow) {
var spot = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 35, this.worldPosition);
IAuraChunk.getAuraChunk(this.level, spot).drainAura(spot, toUse);
}
@ -112,4 +123,9 @@ public class BlockEntityChunkLoader extends BlockEntityImpl implements ITickable
Arrays.stream(compound.getLongArray("forced_chunks")).mapToObj(ChunkPos::new).forEach(this.forcedChunks::add);
}
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}

View file

@ -44,6 +44,8 @@ public class BlockEntityEnderCrate extends BlockEntityImpl implements MenuProvid
@Nonnull
@Override
public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) {
if (!BlockEntityEnderCrate.this.canUseRightNow(20))
return stack;
var remain = this.getStorage().insertItem(slot, stack, simulate);
if (!simulate)
BlockEntityEnderCrate.this.drainAura((stack.getCount() - remain.getCount()) * 20);
@ -53,6 +55,8 @@ public class BlockEntityEnderCrate extends BlockEntityImpl implements MenuProvid
@Nonnull
@Override
public ItemStack extractItem(int slot, int amount, boolean simulate) {
if (!BlockEntityEnderCrate.this.canUseRightNow(20))
return ItemStack.EMPTY;
var extracted = this.getStorage().extractItem(slot, amount, simulate);
if (!simulate)
BlockEntityEnderCrate.this.drainAura(extracted.getCount() * 20);
@ -147,4 +151,9 @@ public class BlockEntityEnderCrate extends BlockEntityImpl implements MenuProvid
public AbstractContainerMenu createMenu(int window, Inventory inv, Player player) {
return new ContainerEnderCrate(ModContainers.ENDER_CRATE, window, player, this.getItemHandler());
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}

View file

@ -56,7 +56,7 @@ public class BlockEntityFieldCreator extends BlockEntityImpl implements ITickabl
if (!this.isMain)
return;
if (this.redstonePower <= 0 && creator.redstonePower <= 0) {
if (this.redstonePower <= 0 && creator.redstonePower <= 0 || !this.canUseRightNow(20)) {
this.chargeTimer = 0;
if (this.isCharged) {
this.isCharged = false;
@ -106,7 +106,6 @@ public class BlockEntityFieldCreator extends BlockEntityImpl implements ITickabl
continue;
var state = this.level.getBlockState(pos);
var block = state.getBlock();
if (!state.isAir() && state.getDestroySpeed(this.level, pos) >= 0F) {
var fake = FakePlayerFactory.getMinecraft((ServerLevel) this.level);
if (!MinecraftForge.EVENT_BUS.post(new BlockEvent.BreakEvent(this.level, pos, state, fake))) {
@ -204,4 +203,9 @@ public class BlockEntityFieldCreator extends BlockEntityImpl implements ITickabl
this.chargeTimer = compound.getInt("timer");
}
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}

View file

@ -64,25 +64,28 @@ public class BlockEntityFurnaceHeater extends BlockEntityImpl implements ITickab
if (burnTime <= 0)
this.level.setBlockAndUpdate(tilePos, this.level.getBlockState(tilePos).setValue(AbstractFurnaceBlock.LIT, true));
data.set(0, 200);
// we leave some wiggle room for the furnace to do its own checks + the blast furnace booster
data.set(2, Math.min(data.get(3) - 2, data.get(2) + 5));
var toDrain = Mth.ceil((200 - burnTime) * 16.6F);
if (this.canUseRightNow(toDrain)) {
data.set(0, 200);
// we leave some wiggle room for the furnace to do its own checks + the blast furnace booster
data.set(2, Math.min(data.get(3) - 2, data.get(2) + 5));
var spot = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 20, this.worldPosition);
var chunk = IAuraChunk.getAuraChunk(this.level, spot);
chunk.drainAura(spot, Mth.ceil((200 - burnTime) * 16.6F));
did = true;
var spot = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 20, this.worldPosition);
var chunk = IAuraChunk.getAuraChunk(this.level, spot);
chunk.drainAura(spot, toDrain);
did = true;
if (this.level.getGameTime() % 15 == 0) {
PacketHandler.sendToAllAround(this.level, this.worldPosition, 32, new PacketParticleStream(
this.worldPosition.getX() + (float) this.level.random.nextGaussian() * 5F,
this.worldPosition.getY() + 1 + this.level.random.nextFloat() * 5F,
this.worldPosition.getZ() + (float) this.level.random.nextGaussian() * 5F,
tilePos.getX() + this.level.random.nextFloat(),
tilePos.getY() + this.level.random.nextFloat(),
tilePos.getZ() + this.level.random.nextFloat(),
this.level.random.nextFloat() * 0.07F + 0.07F, IAuraType.forLevel(this.level).getColor(), this.level.random.nextFloat() + 0.5F
));
if (this.level.getGameTime() % 15 == 0) {
PacketHandler.sendToAllAround(this.level, this.worldPosition, 32, new PacketParticleStream(
this.worldPosition.getX() + (float) this.level.random.nextGaussian() * 5F,
this.worldPosition.getY() + 1 + this.level.random.nextFloat() * 5F,
this.worldPosition.getZ() + (float) this.level.random.nextGaussian() * 5F,
tilePos.getX() + this.level.random.nextFloat(),
tilePos.getY() + this.level.random.nextFloat(),
tilePos.getZ() + this.level.random.nextFloat(),
this.level.random.nextFloat() * 0.07F + 0.07F, IAuraType.forLevel(this.level).getColor(), this.level.random.nextFloat() + 0.5F
));
}
}
}
@ -124,4 +127,9 @@ public class BlockEntityFurnaceHeater extends BlockEntityImpl implements ITickab
if (type == SaveType.SYNC)
this.isActive = compound.getBoolean("active");
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}

View file

@ -44,6 +44,10 @@ public class BlockEntityHopperUpgrade extends BlockEntityImpl implements ITickab
if (items.isEmpty())
return;
var drainPerItem = 500;
if (!this.canUseRightNow(drainPerItem * items.size()))
return;
for (var item : items) {
if (!item.isAlive() || item.hasPickUpDelay())
continue;
@ -65,7 +69,7 @@ public class BlockEntityHopperUpgrade extends BlockEntityImpl implements ITickab
item.kill();
var spot = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 25, this.worldPosition);
IAuraChunk.getAuraChunk(this.level, spot).drainAura(spot, 500);
IAuraChunk.getAuraChunk(this.level, spot).drainAura(spot, drainPerItem);
PacketHandler.sendToAllAround(this.level, this.worldPosition, 32,
new PacketParticles((float) item.getX(), (float) item.getY(), (float) item.getZ(), PacketParticles.Type.HOPPER_UPGRADE));
@ -73,4 +77,9 @@ public class BlockEntityHopperUpgrade extends BlockEntityImpl implements ITickab
}
}
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}

View file

@ -165,6 +165,20 @@ public class BlockEntityImpl extends BlockEntity {
}
}
public boolean canUseRightNow(int toUse) {
if (this.allowsLowerLimiter()) {
for (var dir : Direction.values()) {
var offset = this.worldPosition.relative(dir);
if (this.level.getBlockState(offset).getBlock() == ModBlocks.LOWER_LIMITER) {
var aura = IAuraChunk.getAuraInArea(this.level, this.worldPosition, 35);
return aura - toUse > 0;
}
}
}
return true;
}
public boolean canGenerateRightNow(int toAdd) {
if (this.wantsLimitRemover()) {
var below = this.level.getBlockState(this.worldPosition.below());
@ -179,6 +193,10 @@ public class BlockEntityImpl extends BlockEntity {
return false;
}
public boolean allowsLowerLimiter() {
return false;
}
public void generateAura(int amount) {
while (amount > 0) {
var spot = IAuraChunk.getLowestSpot(this.level, this.worldPosition, 35, this.worldPosition);

View file

@ -0,0 +1,20 @@
package de.ellpeck.naturesaura.blocks.tiles;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.phys.AABB;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
public class BlockEntityLowerLimiter extends BlockEntityImpl {
public BlockEntityLowerLimiter(BlockPos pos, BlockState state) {
super(ModBlockEntities.LOWER_LIMITER, pos, state);
}
@Override
@OnlyIn(Dist.CLIENT)
public AABB getRenderBoundingBox() {
return new AABB(this.worldPosition, this.worldPosition.offset(1, 2, 1));
}
}

View file

@ -44,6 +44,10 @@ public class BlockEntityPlacer extends BlockEntityImpl implements ITickableBlock
if (frames.isEmpty())
return;
var toDrain = 1000;
if (!this.canUseRightNow(toDrain))
return;
List<BlockPos> validPositions = new ArrayList<>();
var range = 5;
for (var x = -range; x <= range; x++)
@ -73,7 +77,7 @@ public class BlockEntityPlacer extends BlockEntityImpl implements ITickableBlock
handler.extractItem(i, 1, false);
var spot = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 10, this.worldPosition);
IAuraChunk.getAuraChunk(this.level, spot).drainAura(spot, 1000);
IAuraChunk.getAuraChunk(this.level, spot).drainAura(spot, toDrain);
PacketHandler.sendToAllAround(this.level, this.worldPosition, 32, new PacketParticles(pos.getX(), pos.getY(), pos.getZ(), PacketParticles.Type.PLACER_PLACING));
@ -82,6 +86,11 @@ public class BlockEntityPlacer extends BlockEntityImpl implements ITickableBlock
}
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
private boolean framesContain(List<ItemFrame> frames, BlockState state) {
var stack = new ItemStack(state.getBlock());
if (stack.isEmpty())

View file

@ -39,6 +39,10 @@ public class BlockEntitySnowCreator extends BlockEntityImpl implements ITickable
if (range <= 0)
return;
var toDrain = 300;
if (!this.canUseRightNow(toDrain))
return;
if (!this.level.isClientSide) {
if (this.level.getGameTime() % 10 != 0)
return;
@ -67,7 +71,7 @@ public class BlockEntitySnowCreator extends BlockEntityImpl implements ITickable
}
var auraPos = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 30, this.worldPosition);
IAuraChunk.getAuraChunk(this.level, auraPos).drainAura(auraPos, 300);
IAuraChunk.getAuraChunk(this.level, auraPos).drainAura(auraPos, toDrain);
PacketHandler.sendToAllAround(this.level, this.worldPosition, 32,
new PacketParticles(this.worldPosition.getX(), this.worldPosition.getY(), this.worldPosition.getZ(), PacketParticles.Type.SNOW_CREATOR));
@ -104,4 +108,9 @@ public class BlockEntitySnowCreator extends BlockEntityImpl implements ITickable
if (type == SaveType.TILE)
this.snowmanCount = compound.getInt("snowman_count");
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}

View file

@ -39,4 +39,9 @@ public class BlockEntitySpawnLamp extends BlockEntityImpl {
if (!this.level.isClientSide)
this.sendToClients();
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}

View file

@ -62,10 +62,9 @@ public class BlockEntitySpring extends BlockEntityImpl implements ITickableBlock
var upState = this.level.getBlockState(up);
if (upState.hasProperty(BlockStateProperties.LEVEL_CAULDRON)) {
int level = upState.getValue(BlockStateProperties.LEVEL_CAULDRON);
if (level < 3) {
if (level < 3 && this.tryConsumeAura(2500)) {
this.level.setBlockAndUpdate(up, upState.setValue(BlockStateProperties.LEVEL_CAULDRON, level + 1));
this.level.playSound(null, up, SoundEvents.BUCKET_FILL, SoundSource.BLOCKS, 1, 1);
this.consumeAura(2500);
return;
}
}
@ -77,10 +76,9 @@ public class BlockEntitySpring extends BlockEntityImpl implements ITickableBlock
for (var z = -spongeRadius; z <= spongeRadius; z++) {
var pos = this.worldPosition.offset(x, y, z);
var state = this.level.getBlockState(pos);
if (state.getBlock() == Blocks.SPONGE) {
if (state.getBlock() == Blocks.SPONGE && this.tryConsumeAura(2500)) {
this.level.setBlock(pos, Blocks.WET_SPONGE.defaultBlockState(), 2);
this.level.levelEvent(2001, pos, Block.getId(Blocks.WATER.defaultBlockState()));
this.consumeAura(2500);
return;
}
}
@ -90,20 +88,18 @@ public class BlockEntitySpring extends BlockEntityImpl implements ITickableBlock
// generate obsidian
for (var dir : Direction.Plane.HORIZONTAL) {
var side = this.worldPosition.relative(dir);
if (this.isLava(side, true)) {
if (this.isLava(side, true) && this.tryConsumeAura(1500)) {
this.level.setBlockAndUpdate(side, ForgeEventFactory.fireFluidPlaceBlockEvent(this.level, side, side, Blocks.OBSIDIAN.defaultBlockState()));
this.level.levelEvent(1501, side, 0);
this.consumeAura(1500);
return;
}
}
// generate stone
var twoUp = this.worldPosition.above(2);
if (this.isLava(twoUp, false) && (this.level.getBlockState(up).isAir() || this.isLava(up, false))) {
if (this.isLava(twoUp, false) && (this.level.getBlockState(up).isAir() || this.isLava(up, false)) && this.tryConsumeAura(150)) {
this.level.setBlockAndUpdate(up, ForgeEventFactory.fireFluidPlaceBlockEvent(this.level, up, twoUp, Blocks.STONE.defaultBlockState()));
this.level.levelEvent(1501, up, 0);
this.consumeAura(150);
return;
}
@ -111,10 +107,9 @@ public class BlockEntitySpring extends BlockEntityImpl implements ITickableBlock
for (var dir : Direction.Plane.HORIZONTAL) {
var twoSide = this.worldPosition.relative(dir, 2);
var side = this.worldPosition.relative(dir);
if (this.isLava(twoSide, false) && (this.level.getBlockState(side).isAir() || this.isLava(side, false))) {
if (this.isLava(twoSide, false) && (this.level.getBlockState(side).isAir() || this.isLava(side, false)) && this.tryConsumeAura(100)) {
this.level.setBlockAndUpdate(side, ForgeEventFactory.fireFluidPlaceBlockEvent(this.level, side, twoSide, Blocks.COBBLESTONE.defaultBlockState()));
this.level.levelEvent(1501, side, 0);
this.consumeAura(100);
return;
}
}
@ -127,11 +122,17 @@ public class BlockEntitySpring extends BlockEntityImpl implements ITickableBlock
return LazyOptional.empty();
}
public void consumeAura(int amount) {
while (amount > 0) {
var pos = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 35, this.worldPosition);
amount -= IAuraChunk.getAuraChunk(this.level, pos).drainAura(pos, amount);
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
public boolean tryConsumeAura(int amount) {
if (!this.canUseRightNow(amount))
return false;
var pos = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 35, this.worldPosition);
IAuraChunk.getAuraChunk(this.level, pos).drainAura(pos, amount);
return true;
}
private boolean isLava(BlockPos offset, boolean source) {
@ -169,8 +170,11 @@ public class BlockEntitySpring extends BlockEntityImpl implements ITickableBlock
@Override
public FluidStack drain(int maxDrain, IFluidHandler.FluidAction action) {
var drain = Math.min(maxDrain, 1000);
var auraUsed = Mth.ceil(drain / 2F);
if (!BlockEntitySpring.this.canUseRightNow(auraUsed))
return FluidStack.EMPTY;
if (action.execute())
BlockEntitySpring.this.consumeAura(Mth.ceil(drain / 2F));
BlockEntitySpring.this.tryConsumeAura(auraUsed);
return new FluidStack(Fluids.WATER, drain);
}

View file

@ -38,7 +38,7 @@ public class BlockEntityTimeChanger extends BlockEntityImpl implements ITickable
if (this.goalTime > 0) {
var current = this.level.getDayTime();
var toAdd = Math.min(75, this.goalTime - current);
if (toAdd <= 0) {
if (toAdd <= 0 || !this.canUseRightNow((int) toAdd * 20)) {
this.goalTime = 0;
this.sendToClients();
return;
@ -118,4 +118,9 @@ public class BlockEntityTimeChanger extends BlockEntityImpl implements ITickable
if (type != SaveType.BLOCK)
this.goalTime = compound.getLong("goal");
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
}

View file

@ -51,9 +51,16 @@ public class BlockEntityWeatherChanger extends BlockEntityImpl implements ITicka
}
if (this.processTime > 0) {
var auraToUse = 30000 * Mth.ceil(this.itemAmount * 0.75F);
if (!this.canUseRightNow(auraToUse)) {
this.processTime = 0;
this.sendToClients();
return;
}
if (this.processTime % 20 == 0) {
var spot = IAuraChunk.getHighestSpot(this.level, this.worldPosition, 35, this.worldPosition);
IAuraChunk.getAuraChunk(this.level, spot).drainAura(spot, 30000 * Mth.ceil(this.itemAmount * 0.75F));
IAuraChunk.getAuraChunk(this.level, spot).drainAura(spot, auraToUse);
}
this.processTime--;
@ -101,6 +108,11 @@ public class BlockEntityWeatherChanger extends BlockEntityImpl implements ITicka
}
}
@Override
public boolean allowsLowerLimiter() {
return true;
}
private Pair<WeatherType, Integer> getNextWeatherType() {
var area = new AABB(this.worldPosition).inflate(2);
var items = this.level.getEntitiesOfClass(ItemEntity.class, area, Entity::isAlive);

View file

@ -2,7 +2,7 @@ package de.ellpeck.naturesaura.blocks.tiles;
import net.minecraft.world.level.block.entity.BlockEntityType;
@SuppressWarnings("NonConstantFieldWithUpperCaseName")
@SuppressWarnings("FieldNamingConvention")
public final class ModBlockEntities {
public static BlockEntityType<BlockEntityAncientLeaves> ANCIENT_LEAVES;
@ -43,4 +43,5 @@ public final class ModBlockEntities {
public static BlockEntityType<BlockEntitySlimeSplitGenerator> SLIME_SPLIT_GENERATOR;
public static BlockEntityType<BlockEntitySpring> SPRING;
public static BlockEntityType<BlockEntityWeatherChanger> WEATHER_CHANGER;
public static BlockEntityType<BlockEntityLowerLimiter> LOWER_LIMITER;
}

View file

@ -34,23 +34,23 @@ public class RenderGeneratorLimitRemover implements BlockEntityRenderer<BlockEnt
public void render(BlockEntityGeneratorLimitRemover te, float v, PoseStack matrixStack, MultiBufferSource iRenderTypeBuffer, int combinedLightIn, int combinedOverlayIn) {
var above = te.getLevel().getBlockEntity(te.getBlockPos().above());
if (above instanceof BlockEntityImpl && ((BlockEntityImpl) above).wantsLimitRemover()) {
this.renderGlint(matrixStack, iRenderTypeBuffer, 1, combinedOverlayIn);
this.renderGlint(matrixStack, iRenderTypeBuffer, 0, combinedOverlayIn);
RenderGeneratorLimitRemover.renderGlint(matrixStack, iRenderTypeBuffer, this.model, 0, 1, 0, combinedOverlayIn, RenderGeneratorLimitRemover.RES, 1);
RenderGeneratorLimitRemover.renderGlint(matrixStack, iRenderTypeBuffer, this.model, 0, 0, 0, combinedOverlayIn, RenderGeneratorLimitRemover.RES, 1);
}
}
private void renderGlint(PoseStack stack, MultiBufferSource buffer, double yOff, int combinedOverlayIn) {
public static void renderGlint(PoseStack stack, MultiBufferSource buffer, ModelLimitRemoverGlint model, int xOff, int yOff, int zOff, int combinedOverlayIn, ResourceLocation texture, float maxAlpha) {
stack.pushPose();
var brightness = 15 << 20 | 15 << 4;
var alpha = ((float) Math.sin(System.currentTimeMillis() / 800D) + 1F) / 2F;
stack.translate(-0.001F, yOff + 1 + 0.001F, 1 + 0.001F);
stack.translate(-0.002F + xOff, 1 + 0.002F + yOff, 1 + 0.002F + zOff);
stack.mulPose(Vector3f.XP.rotationDegrees(180F));
stack.scale(1.002F, 1.002F, 1.002F);
this.model.renderToBuffer(stack, buffer.getBuffer(this.model.renderType(RenderGeneratorLimitRemover.RES)), brightness, combinedOverlayIn, 1, 1, 1, alpha);
stack.scale(1.004F, 1.004F, 1.004F);
model.renderToBuffer(stack, buffer.getBuffer(model.renderType(texture)), brightness, combinedOverlayIn, 1, 1, 1, alpha * maxAlpha);
stack.popPose();
}
private static class ModelLimitRemoverGlint extends Model {
public static class ModelLimitRemoverGlint extends Model {
private final ModelPart model;

View file

@ -0,0 +1,37 @@
package de.ellpeck.naturesaura.blocks.tiles.render;
import com.mojang.blaze3d.vertex.PoseStack;
import de.ellpeck.naturesaura.NaturesAura;
import de.ellpeck.naturesaura.blocks.tiles.BlockEntityImpl;
import de.ellpeck.naturesaura.blocks.tiles.BlockEntityLowerLimiter;
import net.minecraft.client.renderer.MultiBufferSource;
import net.minecraft.client.renderer.blockentity.BlockEntityRenderer;
import net.minecraft.client.renderer.blockentity.BlockEntityRendererProvider;
import net.minecraft.core.Direction;
import net.minecraft.resources.ResourceLocation;
import net.minecraftforge.api.distmarker.Dist;
import net.minecraftforge.api.distmarker.OnlyIn;
import static de.ellpeck.naturesaura.blocks.tiles.render.RenderGeneratorLimitRemover.ModelLimitRemoverGlint;
@OnlyIn(Dist.CLIENT)
public class RenderLowerLimiter implements BlockEntityRenderer<BlockEntityLowerLimiter> {
private static final ResourceLocation RES = new ResourceLocation(NaturesAura.MOD_ID, "textures/models/lower_limiter_glint.png");
private final ModelLimitRemoverGlint model = new ModelLimitRemoverGlint();
public RenderLowerLimiter(BlockEntityRendererProvider.Context context) {}
@Override
public void render(BlockEntityLowerLimiter te, float v, PoseStack matrixStack, MultiBufferSource iRenderTypeBuffer, int combinedLightIn, int combinedOverlayIn) {
for (var dir : Direction.values()) {
var offset = te.getBlockPos().relative(dir);
if (te.getLevel().getBlockEntity(offset) instanceof BlockEntityImpl impl && impl.allowsLowerLimiter()) {
var alpha = te.getLevel().getBlockState(offset).isCollisionShapeFullBlock(te.getLevel(), offset) ? 1 : 0.25F;
RenderGeneratorLimitRemover.renderGlint(matrixStack, iRenderTypeBuffer, this.model, dir.getStepX(), dir.getStepY(), dir.getStepZ(), combinedOverlayIn, RenderLowerLimiter.RES, alpha);
RenderGeneratorLimitRemover.renderGlint(matrixStack, iRenderTypeBuffer, this.model, 0, 0, 0, combinedOverlayIn, RenderLowerLimiter.RES, 1);
}
}
}
}

View file

@ -17,7 +17,7 @@ public class SpreadEffect implements IDrainSpotEffect {
@Override
public void update(Level level, LevelChunk chunk, IAuraChunk auraChunk, BlockPos pos, Integer spot) {
if (Math.abs(spot) < 500000 || Math.abs(IAuraChunk.getAuraInArea(level, pos, 25)) < 2000000)
if (Math.abs(spot) < 500000 || Math.abs(IAuraChunk.getAuraInArea(level, pos, 25) - IAuraChunk.DEFAULT_AURA) < 1000000)
return;
var drain = spot > 0;
var toMove = Mth.ceil(Math.abs(spot) * 0.72F);

View file

@ -7,6 +7,7 @@ import de.ellpeck.naturesaura.data.ItemModelGenerator;
import de.ellpeck.naturesaura.reg.IColorProvidingItem;
import de.ellpeck.naturesaura.reg.ICustomItemModel;
import net.minecraft.client.color.item.ItemColor;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
import net.minecraft.core.dispenser.DefaultDispenseItemBehavior;
import net.minecraft.network.chat.Component;
@ -42,33 +43,15 @@ public class ItemAuraBottle extends ItemImpl implements IColorProvidingItem, ICu
var dispense = stack.split(1);
if (offsetState.isAir()) {
if (IAuraChunk.getAuraInArea(level, offset, 30) >= 100000) {
dispense = ItemAuraBottle.setType(new ItemStack(ItemAuraBottle.this), IAuraType.forLevel(level));
var spot = IAuraChunk.getHighestSpot(level, offset, 30, offset);
IAuraChunk.getAuraChunk(level, spot).drainAura(spot, 20000);
}
var bottle = ItemAuraBottle.create(level, offset);
if (!bottle.isEmpty())
dispense = bottle;
}
DefaultDispenseItemBehavior.spawnItem(level, dispense, 6, facing, DispenserBlock.getDispensePosition(source));
return stack;
});
}
public static IAuraType getType(ItemStack stack) {
if (!stack.hasTag())
return NaturesAuraAPI.TYPE_OTHER;
var type = stack.getTag().getString("stored_type");
if (type.isEmpty())
return NaturesAuraAPI.TYPE_OTHER;
return NaturesAuraAPI.AURA_TYPES.get(new ResourceLocation(type));
}
public static ItemStack setType(ItemStack stack, IAuraType type) {
stack.getOrCreateTag().putString("stored_type", type.getName().toString());
return stack;
}
@Override
public void fillItemCategory(CreativeModeTab tab, NonNullList<ItemStack> items) {
if (this.allowedIn(tab)) {
@ -98,7 +81,34 @@ public class ItemAuraBottle extends ItemImpl implements IColorProvidingItem, ICu
.texture("layer1", "item/" + this.getBaseName() + "_overlay");
}
private class EventHandler {
public static IAuraType getType(ItemStack stack) {
if (!stack.hasTag())
return NaturesAuraAPI.TYPE_OTHER;
var type = stack.getTag().getString("stored_type");
if (type.isEmpty())
return NaturesAuraAPI.TYPE_OTHER;
return NaturesAuraAPI.AURA_TYPES.get(new ResourceLocation(type));
}
public static ItemStack setType(ItemStack stack, IAuraType type) {
stack.getOrCreateTag().putString("stored_type", type.getName().toString());
return stack;
}
private static ItemStack create(Level level, BlockPos pos) {
var aura = IAuraChunk.getAuraInArea(level, pos, 30);
if (aura <= -100000) {
return new ItemStack(ModItems.VACUUM_BOTTLE);
} else if (aura >= 100000) {
var spot = IAuraChunk.getHighestSpot(level, pos, 30, pos);
IAuraChunk.getAuraChunk(level, spot).drainAura(spot, 20000);
return ItemAuraBottle.setType(new ItemStack(ModItems.AURA_BOTTLE), IAuraType.forLevel(level));
} else {
return ItemStack.EMPTY;
}
}
private static class EventHandler {
@SubscribeEvent
public void onRightClick(PlayerInteractEvent.RightClickItem event) {
@ -109,23 +119,19 @@ public class ItemAuraBottle extends ItemImpl implements IColorProvidingItem, ICu
HitResult ray = Item.getPlayerPOVHitResult(player.level, player, ClipContext.Fluid.NONE);
if (ray.getType() == HitResult.Type.BLOCK)
return;
var pos = player.blockPosition();
if (IAuraChunk.getAuraInArea(player.level, pos, 30) < 100000)
var bottle = ItemAuraBottle.create(player.level, player.blockPosition());
if (bottle.isEmpty())
return;
if (!player.level.isClientSide) {
held.shrink(1);
var stack = ItemAuraBottle.setType(new ItemStack(ItemAuraBottle.this), IAuraType.forLevel(player.level));
if (!player.addItem(stack))
player.level.addFreshEntity(new ItemEntity(player.level, player.getX(), player.getY(), player.getZ(), stack));
var spot = IAuraChunk.getHighestSpot(player.level, pos, 30, pos);
IAuraChunk.getAuraChunk(player.level, spot).drainAura(spot, 20000);
if (!player.addItem(bottle))
player.level.addFreshEntity(new ItemEntity(player.level, player.getX(), player.getY(), player.getZ(), bottle));
player.level.playSound(null, player.getX(), player.getY(), player.getZ(),
SoundEvents.BOTTLE_FILL_DRAGONBREATH, SoundSource.PLAYERS, 1F, 1F);
}
player.swing(event.getHand());
}

View file

@ -64,4 +64,5 @@ public final class ModItems {
public static Item BREAK_PREVENTION;
public static Item PET_REVIVER;
public static Item NETHERITE_FINDER;
public static Item VACUUM_BOTTLE;
}

View file

@ -133,7 +133,9 @@ public final class ModRegistry {
new BlockSpring(),
new BlockWeatherChanger(),
new BlockRFConverter(),
new BlockChunkLoader());
new BlockChunkLoader(),
new BlockLowerLimiter()
);
Helper.populateObjectHolders(ModBlocks.class, event.getForgeRegistry());
});
@ -206,7 +208,8 @@ public final class ModRegistry {
new ItemStructureFinder("outpost_finder", BuiltinStructures.PILLAGER_OUTPOST, 0xab9f98, 2048),
new ItemBreakPrevention(),
new ItemPetReviver(),
new ItemNetheriteFinder()
new ItemNetheriteFinder(),
new ItemImpl("vacuum_bottle")
);
Helper.populateObjectHolders(ModItems.class, event.getForgeRegistry());
});

View file

@ -78,6 +78,7 @@
"block.naturesaura.slime_split_generator": "Offshoot Observer",
"block.naturesaura.spring": "Everlasting Spring",
"block.naturesaura.weather_changer": "Cloudshifter",
"block.naturesaura.lower_limiter": "Aura Imbalance Ward",
"item.naturesaura.eye": "Environmental Eye",
"item.naturesaura.eye_improved": "Environmental Ocular",
"item.naturesaura.gold_fiber": "Brilliant Fiber",
@ -94,6 +95,7 @@
"item.naturesaura.book.name": "Book of Natural Aura",
"item.naturesaura.shockwave_creator": "Amulet of Wrath",
"item.naturesaura.multiblock_maker": "Multiblock Maker",
"item.naturesaura.vacuum_bottle": "Bottled Vacuum",
"item.naturesaura.aura_bottle.naturesaura:overworld": "Bottled Sunlight",
"item.naturesaura.aura_bottle.naturesaura:nether": "Bottled Ghosts",
"item.naturesaura.aura_bottle.naturesaura:end": "Bottled Darkness",
@ -191,11 +193,11 @@
"advancement.naturesaura.infused_tools": "Gear Up Intensifies",
"advancement.naturesaura.infused_tools.desc": "Create an Infused Iron Pickaxe and Blade",
"advancement.naturesaura.aura_bottle_overworld": "A Taste of Sunlight",
"advancement.naturesaura.aura_bottle_overworld.desc": "Collect Aura using a Bottle in the Overworld",
"advancement.naturesaura.aura_bottle_overworld.desc": "Collect Aura using a Bottle and Cork in the Overworld",
"advancement.naturesaura.aura_bottle_nether": "Spooky Scary Skeletons",
"advancement.naturesaura.aura_bottle_nether.desc": "Collect Aura using a Bottle in the Nether",
"advancement.naturesaura.aura_bottle_nether.desc": "Collect Aura using a Bottle and Cork in the Nether",
"advancement.naturesaura.aura_bottle_end": "Breathy Surroundings",
"advancement.naturesaura.aura_bottle_end.desc": "Collect Aura using a Bottle in the End",
"advancement.naturesaura.aura_bottle_end.desc": "Collect Aura using a Bottle and Cork in the End",
"advancement.naturesaura.offering": "Yo God, Ya Want This?",
"advancement.naturesaura.offering.desc": "Create an Offering Table for the Offering to the Gods",
"advancement.naturesaura.sky_ingot": "Sturdy and Light",
@ -214,6 +216,8 @@
"advancement.naturesaura.eye_improved.desc": "Create an Environmental Ocular to see Aura imbalance effects",
"advancement.naturesaura.range_visualizer": "I Spy With my Little Eye",
"advancement.naturesaura.range_visualizer.desc": "Create a Mystical Magnifier to see the range of your devices",
"advancement.naturesaura.vacuum_bottle": "Breathe Through, Breathe Deep",
"advancement.naturesaura.vacuum_bottle.desc": "Capture a vacuum using a Bottle and Cork",
"command.naturesaura.aura.usage": "/naaura store|drain <amount> [range] OR /naaura reset <range>",
"effect.naturesaura.breathless": "Breathless",
"entity.naturesaura.effect_inhibitor": "Effect Powder",

View file

@ -1,6 +1,6 @@
{
"parent": "minecraft:block/block",
"render_type": "translucent",
"render_type": "cutout_mipped",
"ambientocclusion": false,
"textures": {
"particle": "naturesaura:block/spring",

View file

@ -2,7 +2,7 @@
"name": "Disentangler of Mortals",
"icon": "naturesaura:animal_generator",
"category": "naturesaura:creating",
"advancement": "naturesaura:tainted_gold",
"advancement": "naturesaura:infused_materials",
"pages": [
{
"type": "text",

View file

@ -2,7 +2,7 @@
"name": "Shooting Mark",
"icon": "naturesaura:projectile_generator",
"category": "naturesaura:creating",
"advancement": "naturesaura:tainted_gold",
"advancement": "naturesaura:infused_materials",
"pages": [
{
"type": "text",

View file

@ -2,7 +2,7 @@
"name": "Offshoot Observer",
"icon": "naturesaura:slime_split_generator",
"category": "naturesaura:creating",
"advancement": "naturesaura:tainted_gold",
"advancement": "naturesaura:infused_materials",
"pages": [
{
"type": "text",

View file

@ -2,7 +2,7 @@
"name": "Amulet of Wrath",
"icon": "naturesaura:shockwave_creator",
"category": "naturesaura:items",
"advancement": "naturesaura:tainted_gold",
"advancement": "naturesaura:infused_materials",
"pages": [
{
"type": "text",

View file

@ -23,6 +23,12 @@
{
"type": "text",
"text": "Additionally, the collection of $(aura) in this manner can be automated easily using $(item)Dispensers$(): Putting empty $(item)Bottles and Corks$() into them will cause them to be shot out open, making them fill up with $(aura) in the process. As they are not sucked up by the Dispenser again afterwards, an additional tool like a $(item)Hopper$() is required."
},
{
"type": "spotlight",
"item": "naturesaura:vacuum_bottle",
"link_recipe": true,
"text": "Lastly, some areas have a severe lack of $(aura), much lower than the $(l:items/eye)Environmental Eye$() can display, and whose air is subsequently nearly devoid of oxygen. Using a $(item)Bottle and Cork$() in areas like these allows bottling up this air and capturing a nearly perfect vacuum in the bottle."
}
]
}

View file

@ -2,7 +2,7 @@
"name": "Offering to the Gods",
"icon": "naturesaura:offering_table",
"category": "naturesaura:practices",
"advancement": "naturesaura:tainted_gold",
"advancement": "naturesaura:infused_materials",
"pages": [
{
"type": "text",

View file

@ -0,0 +1,18 @@
{
"name": "Aura Imbalance Ward",
"icon": "naturesaura:lower_limiter",
"category": "naturesaura:using",
"advancement": "naturesaura:vacuum_bottle",
"priority": true,
"pages": [
{
"type": "text",
"text": "As any magical botanist knows, causing negative $(aura) imbalance effects can be quite dangerous, especially when using a device that consumes $(aura) passively.$(br)For cases like this, the $(item)Aura Imbalance Ward$() provides protection against any dangers: placing it next to a device that uses $(aura) causes the device to cease operation while the $(aura) levels around it are too low.$(br)This comes at no cost in return."
},
{
"type": "crafting",
"recipe": "naturesaura:lower_limiter",
"text": "Crafting the $(item)Aura Imbalance Ward$()"
}
]
}

View file

@ -2,7 +2,7 @@
"name": "Amulet of Wrath",
"icon": "naturesaura:shockwave_creator",
"category": "naturesaura:items",
"advancement": "naturesaura:tainted_gold",
"advancement": "naturesaura:infused_materials",
"pages": [
{
"type": "text",

View file

@ -2,7 +2,7 @@
"name": "Offering to the Gods",
"icon": "naturesaura:offering_table",
"category": "naturesaura:practices",
"advancement": "naturesaura:tainted_gold",
"advancement": "naturesaura:infused_materials",
"pages": [
{
"type": "text",

View file

@ -2,7 +2,7 @@
"name": "分裂观测仪",
"icon": "naturesaura:slime_split_generator",
"category": "naturesaura:creating",
"advancement": "naturesaura:tainted_gold",
"advancement": "naturesaura:infused_materials",
"pages": [
{
"type": "text",

View file

@ -2,7 +2,7 @@
"name": "狂怒护身符",
"icon": "naturesaura:shockwave_creator",
"category": "naturesaura:items",
"advancement": "naturesaura:tainted_gold",
"advancement": "naturesaura:infused_materials",
"pages": [
{
"type": "text",

View file

@ -2,7 +2,7 @@
"name": "祭祀诸神",
"icon": "naturesaura:offering_table",
"category": "naturesaura:practices",
"advancement": "naturesaura:tainted_gold",
"advancement": "naturesaura:infused_materials",
"pages": [
{
"type": "text",

Binary file not shown.

After

Width:  |  Height:  |  Size: 690 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 739 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 270 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 418 B

View file

@ -0,0 +1,26 @@
{
"display": {
"icon": {
"item": "naturesaura:vacuum_bottle"
},
"title": {
"translate": "advancement.naturesaura.vacuum_bottle"
},
"description": {
"translate": "advancement.naturesaura.vacuum_bottle.desc"
}
},
"parent": "naturesaura:negative_imbalance",
"criteria": {
"bottle": {
"trigger": "minecraft:inventory_changed",
"conditions": {
"items": [
{
"items": ["naturesaura:vacuum_bottle"]
}
]
}
}
}
}

View file

@ -0,0 +1,31 @@
{
"type": "minecraft:crafting_shaped",
"pattern": [
"S1S",
"2I3",
"S4S"
],
"key": {
"S": {
"item": "naturesaura:infused_stone"
},
"1": {
"item": "naturesaura:token_euphoria"
},
"2": {
"item": "naturesaura:token_terror"
},
"3": {
"item": "naturesaura:token_rage"
},
"4": {
"item": "naturesaura:token_grief"
},
"I": {
"item": "naturesaura:vacuum_bottle"
}
},
"result": {
"item": "naturesaura:lower_limiter"
}
}