diff --git a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java index 2d2db39c..55b168d3 100644 --- a/src/main/java/de/ellpeck/naturesaura/NaturesAura.java +++ b/src/main/java/de/ellpeck/naturesaura/NaturesAura.java @@ -7,6 +7,7 @@ import de.ellpeck.naturesaura.aura.chunk.AuraChunk; import de.ellpeck.naturesaura.aura.container.IAuraContainer; import de.ellpeck.naturesaura.aura.item.IAuraRecharge; import de.ellpeck.naturesaura.blocks.ModBlocks; +import de.ellpeck.naturesaura.commands.CommandAura; import de.ellpeck.naturesaura.compat.Compat; import de.ellpeck.naturesaura.events.CommonEvents; 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.FMLPostInitializationEvent; 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.Logger; @@ -81,4 +83,9 @@ public final class NaturesAura { ModRegistry.postInit(event); proxy.postInit(event); } + + @EventHandler + public void serverStarting(FMLServerStartingEvent event) { + event.registerServerCommand(new CommandAura()); + } } diff --git a/src/main/java/de/ellpeck/naturesaura/aura/chunk/AuraChunk.java b/src/main/java/de/ellpeck/naturesaura/aura/chunk/AuraChunk.java index 331100c6..f941a148 100644 --- a/src/main/java/de/ellpeck/naturesaura/aura/chunk/AuraChunk.java +++ b/src/main/java/de/ellpeck/naturesaura/aura/chunk/AuraChunk.java @@ -1,8 +1,9 @@ package de.ellpeck.naturesaura.aura.chunk; -import de.ellpeck.naturesaura.Helper; 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.PacketHandler; import net.minecraft.nbt.NBTBase; @@ -34,10 +35,13 @@ public class AuraChunk implements ICapabilityProvider, INBTSerializable drainSpots = new HashMap<>(); + private final List effects = new ArrayList<>(); private boolean needsSync; public AuraChunk(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 consumer) { @@ -72,7 +76,7 @@ public class AuraChunk implements ICapabilityProvider, INBTSerializable closestSpot = new MutableObject<>(); getSpotsInArea(world, pos, radius, (blockPos, drainSpot) -> { double dist = pos.distanceSq(blockPos); - if (dist < radius * radius && dist < closestDist.doubleValue()) { + if (dist < closestDist.doubleValue()) { closestDist.setValue(dist); closestSpot.setValue(blockPos); } @@ -136,32 +140,9 @@ public class AuraChunk implements ICapabilityProvider, INBTSerializable entry : this.drainSpots.entrySet()) { - BlockPos pos = entry.getKey(); - int amount = entry.getValue().intValue(); - if (amount < 0) { - List 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; - } - } - } - } + for (Map.Entry entry : this.drainSpots.entrySet()) { + for (IDrainSpotEffect effect : this.effects) { + effect.update(world, this.chunk, this, entry.getKey(), entry.getValue()); } } } diff --git a/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/GrassDieEffect.java b/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/GrassDieEffect.java new file mode 100644 index 00000000..0557f96b --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/GrassDieEffect.java @@ -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); + } + } + } + } + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/IDrainSpotEffect.java b/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/IDrainSpotEffect.java new file mode 100644 index 00000000..0edf881e --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/IDrainSpotEffect.java @@ -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); + +} diff --git a/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/ReplenishingEffect.java b/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/ReplenishingEffect.java new file mode 100644 index 00000000..ca12c776 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/aura/chunk/effect/ReplenishingEffect.java @@ -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 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; + } + } + } + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/blocks/BlockImpl.java b/src/main/java/de/ellpeck/naturesaura/blocks/BlockImpl.java index eb1fafd8..c61d766a 100644 --- a/src/main/java/de/ellpeck/naturesaura/blocks/BlockImpl.java +++ b/src/main/java/de/ellpeck/naturesaura/blocks/BlockImpl.java @@ -1,21 +1,15 @@ package de.ellpeck.naturesaura.blocks; -import de.ellpeck.naturesaura.NaturesAura; import de.ellpeck.naturesaura.reg.IModItem; import de.ellpeck.naturesaura.reg.IModelProvider; import de.ellpeck.naturesaura.reg.ModRegistry; import net.minecraft.block.Block; import net.minecraft.block.SoundType; 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.FMLPostInitializationEvent; import net.minecraftforge.fml.common.event.FMLPreInitializationEvent; -import java.util.Collections; -import java.util.Map; - public class BlockImpl extends Block implements IModItem, IModelProvider { private final String baseName; diff --git a/src/main/java/de/ellpeck/naturesaura/commands/CommandAura.java b/src/main/java/de/ellpeck/naturesaura/commands/CommandAura.java new file mode 100644 index 00000000..f0718f66 --- /dev/null +++ b/src/main/java/de/ellpeck/naturesaura/commands/CommandAura.java @@ -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 getTabCompletions(MinecraftServer server, ICommandSender sender, String[] args, @Nullable BlockPos targetPos) { + if (args.length == 1) { + return getListOfStringsMatchingLastWord(args, "add", "remove"); + } else { + return Collections.emptyList(); + } + } +} diff --git a/src/main/java/de/ellpeck/naturesaura/events/ClientEvents.java b/src/main/java/de/ellpeck/naturesaura/events/ClientEvents.java index 70723386..18dc7df2 100644 --- a/src/main/java/de/ellpeck/naturesaura/events/ClientEvents.java +++ b/src/main/java/de/ellpeck/naturesaura/events/ClientEvents.java @@ -49,14 +49,18 @@ public class ClientEvents { left.add(""); 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 spots = new MutableInt(); AuraChunk.getSpotsInArea(mc.world, mc.player.getPosition(), 15, ((blockPos, drainSpot) -> { spots.increment(); 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 + "DrainSpots: " + spots.intValue()); + left.add(prefix + "Aura: " + amount.intValue() + " in " + spots.intValue() + " spots"); } } diff --git a/src/main/resources/assets/naturesaura/lang/en_US.lang b/src/main/resources/assets/naturesaura/lang/en_US.lang index 9675a953..e5b0d982 100644 --- a/src/main/resources/assets/naturesaura/lang/en_US.lang +++ b/src/main/resources/assets/naturesaura/lang/en_US.lang @@ -41,4 +41,6 @@ advancement.naturesaura.wood_stand.desc=Create a Wooden Stand for the Ritual of advancement.naturesaura.altar=Empowered advancement.naturesaura.altar.desc=Create a Natural Altar using the Ritual of the Forest advancement.naturesaura.infused_materials=Iron Factory -advancement.naturesaura.infused_materials.desc=Use the Natural Altar to create Infused Iron and Infused Rock \ No newline at end of file +advancement.naturesaura.infused_materials.desc=Use the Natural Altar to create Infused Iron and Infused Rock + +command.naturesaura.aura.usage=/naaura \ No newline at end of file diff --git a/src/main/resources/assets/naturesaura/patchouli_books/en_us/entries/collecting/altar.json b/src/main/resources/assets/naturesaura/patchouli_books/en_us/entries/collecting/altar.json index 0ed48bce..fc27e599 100644 --- a/src/main/resources/assets/naturesaura/patchouli_books/en_us/entries/collecting/altar.json +++ b/src/main/resources/assets/naturesaura/patchouli_books/en_us/entries/collecting/altar.json @@ -7,7 +7,7 @@ "pages": [ { "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",