add the first diminishing return and a command to manipulate aura

This commit is contained in:
Ellpeck 2018-10-25 18:49:42 +02:00
parent 745afd6975
commit 65a29541ad
10 changed files with 197 additions and 39 deletions

View file

@ -7,6 +7,7 @@ import de.ellpeck.naturesaura.aura.chunk.AuraChunk;
import de.ellpeck.naturesaura.aura.container.IAuraContainer; import de.ellpeck.naturesaura.aura.container.IAuraContainer;
import de.ellpeck.naturesaura.aura.item.IAuraRecharge; import de.ellpeck.naturesaura.aura.item.IAuraRecharge;
import de.ellpeck.naturesaura.blocks.ModBlocks; import de.ellpeck.naturesaura.blocks.ModBlocks;
import de.ellpeck.naturesaura.commands.CommandAura;
import de.ellpeck.naturesaura.compat.Compat; import de.ellpeck.naturesaura.compat.Compat;
import de.ellpeck.naturesaura.events.CommonEvents; import de.ellpeck.naturesaura.events.CommonEvents;
import de.ellpeck.naturesaura.events.TerrainGenEvents; import de.ellpeck.naturesaura.events.TerrainGenEvents;
@ -25,6 +26,7 @@ import net.minecraftforge.fml.common.SidedProxy;
import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import net.minecraftforge.fml.common.event.FMLServerStartingEvent;
import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.Logger;
@ -81,4 +83,9 @@ public final class NaturesAura {
ModRegistry.postInit(event); ModRegistry.postInit(event);
proxy.postInit(event); proxy.postInit(event);
} }
@EventHandler
public void serverStarting(FMLServerStartingEvent event) {
event.registerServerCommand(new CommandAura());
}
} }

View file

@ -1,8 +1,9 @@
package de.ellpeck.naturesaura.aura.chunk; package de.ellpeck.naturesaura.aura.chunk;
import de.ellpeck.naturesaura.Helper;
import de.ellpeck.naturesaura.aura.Capabilities; import de.ellpeck.naturesaura.aura.Capabilities;
import de.ellpeck.naturesaura.aura.container.IAuraContainer; import de.ellpeck.naturesaura.aura.chunk.effect.GrassDieEffect;
import de.ellpeck.naturesaura.aura.chunk.effect.IDrainSpotEffect;
import de.ellpeck.naturesaura.aura.chunk.effect.ReplenishingEffect;
import de.ellpeck.naturesaura.packet.PacketAuraChunk; import de.ellpeck.naturesaura.packet.PacketAuraChunk;
import de.ellpeck.naturesaura.packet.PacketHandler; import de.ellpeck.naturesaura.packet.PacketHandler;
import net.minecraft.nbt.NBTBase; import net.minecraft.nbt.NBTBase;
@ -34,10 +35,13 @@ public class AuraChunk implements ICapabilityProvider, INBTSerializable<NBTTagCo
private final Chunk chunk; private final Chunk chunk;
private final Map<BlockPos, MutableInt> drainSpots = new HashMap<>(); private final Map<BlockPos, MutableInt> drainSpots = new HashMap<>();
private final List<IDrainSpotEffect> effects = new ArrayList<>();
private boolean needsSync; private boolean needsSync;
public AuraChunk(Chunk chunk) { public AuraChunk(Chunk chunk) {
this.chunk = chunk; this.chunk = chunk;
this.effects.add(new ReplenishingEffect());
this.effects.add(new GrassDieEffect());
} }
public static void getSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, MutableInt> consumer) { public static void getSpotsInArea(World world, BlockPos pos, int radius, BiConsumer<BlockPos, MutableInt> consumer) {
@ -72,7 +76,7 @@ public class AuraChunk implements ICapabilityProvider, INBTSerializable<NBTTagCo
MutableObject<BlockPos> closestSpot = new MutableObject<>(); MutableObject<BlockPos> closestSpot = new MutableObject<>();
getSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> { getSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> {
double dist = pos.distanceSq(blockPos); double dist = pos.distanceSq(blockPos);
if (dist < radius * radius && dist < closestDist.doubleValue()) { if (dist < closestDist.doubleValue()) {
closestDist.setValue(dist); closestDist.setValue(dist);
closestSpot.setValue(blockPos); closestSpot.setValue(blockPos);
} }
@ -136,32 +140,9 @@ public class AuraChunk implements ICapabilityProvider, INBTSerializable<NBTTagCo
this.needsSync = false; this.needsSync = false;
} }
if (world.getTotalWorldTime() % 40 == 0) {
for (Map.Entry<BlockPos, MutableInt> entry : this.drainSpots.entrySet()) { for (Map.Entry<BlockPos, MutableInt> entry : this.drainSpots.entrySet()) {
BlockPos pos = entry.getKey(); for (IDrainSpotEffect effect : this.effects) {
int amount = entry.getValue().intValue(); effect.update(world, this.chunk, this, entry.getKey(), entry.getValue());
if (amount < 0) {
List<ISpotDrainable> tiles = new ArrayList<>();
Helper.getTileEntitiesInArea(world, pos, 25, tile -> {
if (tile.hasCapability(Capabilities.auraContainer, null)) {
IAuraContainer container = tile.getCapability(Capabilities.auraContainer, null);
if (container instanceof ISpotDrainable) {
tiles.add((ISpotDrainable) container);
}
}
});
if (!tiles.isEmpty()) {
for (int i = world.rand.nextInt(10) + 5; i >= 0; i--) {
ISpotDrainable tile = tiles.get(world.rand.nextInt(tiles.size()));
int drained = tile.drainAuraPassively(-amount, false);
this.storeAura(pos, drained);
amount += drained;
if (amount >= drained) {
break;
}
}
}
}
} }
} }
} }

View file

@ -0,0 +1,48 @@
package de.ellpeck.naturesaura.aura.chunk.effect;
import de.ellpeck.naturesaura.aura.chunk.AuraChunk;
import de.ellpeck.naturesaura.blocks.ModBlocks;
import net.minecraft.block.*;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import org.apache.commons.lang3.mutable.MutableInt;
public class GrassDieEffect implements IDrainSpotEffect {
@Override
public void update(World world, Chunk chunk, AuraChunk auraChunk, BlockPos pos, MutableInt spot) {
if (spot.intValue() < 0) {
int aura = AuraChunk.getAuraInArea(world, pos, 25);
if (aura < 0) {
int amount = Math.min(300, Math.abs(aura) / 1000);
if (amount > 0) {
int dist = 25;
for (int i = amount / 2 + world.rand.nextInt(amount / 2); i >= 0; i--) {
BlockPos grassPos = new BlockPos(
pos.getX() + world.rand.nextGaussian() * dist,
pos.getY() + world.rand.nextGaussian() * dist,
pos.getZ() + world.rand.nextGaussian() * dist
);
if (grassPos.distanceSq(pos) <= dist * dist && world.isBlockLoaded(grassPos)) {
IBlockState state = world.getBlockState(grassPos);
Block block = state.getBlock();
IBlockState newState = null;
if (block instanceof BlockLeaves) {
newState = ModBlocks.DECAYED_LEAVES.getDefaultState();
} else if (block instanceof BlockGrass) {
newState = Blocks.DIRT.getDefaultState().withProperty(BlockDirt.VARIANT, BlockDirt.DirtType.COARSE_DIRT);
} else if (block instanceof BlockBush) {
newState = Blocks.AIR.getDefaultState();
}
if (newState != null)
world.setBlockState(grassPos, newState);
}
}
}
}
}
}
}

View file

@ -0,0 +1,13 @@
package de.ellpeck.naturesaura.aura.chunk.effect;
import de.ellpeck.naturesaura.aura.chunk.AuraChunk;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import org.apache.commons.lang3.mutable.MutableInt;
public interface IDrainSpotEffect {
void update(World world, Chunk chunk, AuraChunk auraChunk, BlockPos pos, MutableInt spot);
}

View file

@ -0,0 +1,43 @@
package de.ellpeck.naturesaura.aura.chunk.effect;
import de.ellpeck.naturesaura.Helper;
import de.ellpeck.naturesaura.aura.Capabilities;
import de.ellpeck.naturesaura.aura.chunk.AuraChunk;
import de.ellpeck.naturesaura.aura.chunk.ISpotDrainable;
import de.ellpeck.naturesaura.aura.container.IAuraContainer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk;
import org.apache.commons.lang3.mutable.MutableInt;
import java.util.ArrayList;
import java.util.List;
public class ReplenishingEffect implements IDrainSpotEffect {
@Override
public void update(World world, Chunk chunk, AuraChunk auraChunk, BlockPos pos, MutableInt spot) {
int amount = spot.intValue();
if (amount < 0) {
List<ISpotDrainable> tiles = new ArrayList<>();
Helper.getTileEntitiesInArea(world, pos, 25, tile -> {
if (tile.hasCapability(Capabilities.auraContainer, null)) {
IAuraContainer container = tile.getCapability(Capabilities.auraContainer, null);
if (container instanceof ISpotDrainable) {
tiles.add((ISpotDrainable) container);
}
}
});
if (!tiles.isEmpty()) {
for (int i = world.rand.nextInt(6); i >= 0; i--) {
ISpotDrainable tile = tiles.get(world.rand.nextInt(tiles.size()));
int drained = tile.drainAuraPassively(-amount, false);
auraChunk.storeAura(pos, drained);
amount += drained;
if (amount >= drained) {
break;
}
}
}
}
}
}

View file

@ -1,21 +1,15 @@
package de.ellpeck.naturesaura.blocks; package de.ellpeck.naturesaura.blocks;
import de.ellpeck.naturesaura.NaturesAura;
import de.ellpeck.naturesaura.reg.IModItem; import de.ellpeck.naturesaura.reg.IModItem;
import de.ellpeck.naturesaura.reg.IModelProvider; import de.ellpeck.naturesaura.reg.IModelProvider;
import de.ellpeck.naturesaura.reg.ModRegistry; import de.ellpeck.naturesaura.reg.ModRegistry;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.SoundType; import net.minecraft.block.SoundType;
import net.minecraft.block.material.Material; import net.minecraft.block.material.Material;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.fml.common.event.FMLInitializationEvent; import net.minecraftforge.fml.common.event.FMLInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPostInitializationEvent;
import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent;
import java.util.Collections;
import java.util.Map;
public class BlockImpl extends Block implements IModItem, IModelProvider { public class BlockImpl extends Block implements IModItem, IModelProvider {
private final String baseName; private final String baseName;

View file

@ -0,0 +1,66 @@
package de.ellpeck.naturesaura.commands;
import de.ellpeck.naturesaura.NaturesAura;
import de.ellpeck.naturesaura.aura.chunk.AuraChunk;
import net.minecraft.command.*;
import net.minecraft.server.MinecraftServer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.world.World;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.List;
public class CommandAura extends CommandBase {
@Override
public String getName() {
return "naaura";
}
@Override
public String getUsage(ICommandSender sender) {
return "command." + NaturesAura.MOD_ID + ".aura.usage";
}
@Override
public void execute(MinecraftServer server, ICommandSender sender, String[] args) throws CommandException {
if (args.length != 3) {
throw new SyntaxErrorException("Wrong number of arguments");
}
String action = args[0];
int amount;
int range;
try {
amount = Integer.parseInt(args[1]);
range = Integer.parseInt(args[2]);
} catch (Exception e) {
throw new NumberInvalidException("Invalid number");
}
World world = sender.getEntityWorld();
BlockPos pos = sender.getPosition();
BlockPos spot = AuraChunk.getClosestSpot(world, pos, range, pos);
AuraChunk chunk = AuraChunk.getAuraChunk(world, spot);
if ("add".equals(action)) {
chunk.storeAura(spot, amount);
sender.sendMessage(new TextComponentString("Added " + amount + " aura"));
} else if ("remove".equals(action)) {
chunk.drainAura(spot, amount);
sender.sendMessage(new TextComponentString("Removed " + amount + " aura"));
} else {
throw new SyntaxErrorException("Invalid action " + action);
}
}
@Override
public List<String> getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos targetPos) {
if (args.length == 1) {
return getListOfStringsMatchingLastWord(args, "add", "remove");
} else {
return Collections.emptyList();
}
}
}

View file

@ -49,14 +49,18 @@ public class ClientEvents {
left.add(""); left.add("");
left.add(prefix + "PartScrn: " + ParticleHandler.getParticleAmount()); left.add(prefix + "PartScrn: " + ParticleHandler.getParticleAmount());
boolean adv = mc.gameSettings.showDebugProfilerChart;
if (adv)
left.add(prefix + "DrainSpots:");
MutableInt amount = new MutableInt(AuraChunk.DEFAULT_AURA); MutableInt amount = new MutableInt(AuraChunk.DEFAULT_AURA);
MutableInt spots = new MutableInt(); MutableInt spots = new MutableInt();
AuraChunk.getSpotsInArea(mc.world, mc.player.getPosition(), 15, ((blockPos, drainSpot) -> { AuraChunk.getSpotsInArea(mc.world, mc.player.getPosition(), 15, ((blockPos, drainSpot) -> {
spots.increment(); spots.increment();
amount.add(drainSpot.intValue()); amount.add(drainSpot.intValue());
if (adv)
left.add(prefix + drainSpot.intValue() + " @ " + blockPos.getX()+" "+blockPos.getY()+" "+blockPos.getZ());
})); }));
left.add(prefix + "Aura: " + amount.intValue()); left.add(prefix + "Aura: " + amount.intValue() + " in " + spots.intValue() + " spots");
left.add(prefix + "DrainSpots: " + spots.intValue());
} }
} }

View file

@ -42,3 +42,5 @@ advancement.naturesaura.altar=Empowered
advancement.naturesaura.altar.desc=Create a Natural Altar using the Ritual of the Forest advancement.naturesaura.altar.desc=Create a Natural Altar using the Ritual of the Forest
advancement.naturesaura.infused_materials=Iron Factory advancement.naturesaura.infused_materials=Iron Factory
advancement.naturesaura.infused_materials.desc=Use the Natural Altar to create Infused Iron and Infused Rock advancement.naturesaura.infused_materials.desc=Use the Natural Altar to create Infused Iron and Infused Rock
command.naturesaura.aura.usage=/naaura <action> <amount> <range>

View file

@ -7,7 +7,7 @@
"pages": [ "pages": [
{ {
"type": "text", "type": "text",
"text": "A rudimentary, yet effective way of collecting $(thing)Aura$() early on is the $(item)Natural Altar$(). After creating the setup shown on the following page, the altar will start slowly draining $(thing)Aura$() in the vicinity.$(br)The collected $(thing)Aura$() can then be used in several ways, $(l:naturesaura:using/altar)infusing items$() for instance." "text": "A rudimentary, yet effective way of collecting $(thing)Aura$() early on is the $(item)Natural Altar$(). After creating the setup shown on the following page, the altar will start slowly draining $(thing)Aura$() in the vicinity. However, it is not strong enough to cause major damage, making it only drain until there is none left in the area.$(br)The collected $(thing)Aura$() can then be used in several ways, $(l:naturesaura:using/altar)infusing items$() for instance."
}, },
{ {
"type": "naturesaura:tree_ritual", "type": "naturesaura:tree_ritual",